Class: LeapCli::SshKey

Inherits:
Object show all
Extended by:
Forwardable
Defined in:
lib/leap_cli/ssh_key.rb

Constant Summary collapse

SUPPORTED_TYPES =

supported ssh key types, in order of preference

['ssh-rsa', 'ecdsa-sha2-nistp256']
SUPPORTED_TYPES_RE =
/(#{SUPPORTED_TYPES.join('|')})/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rsa_key) ⇒ SshKey

Returns a new instance of SshKey.



133
134
135
# File 'lib/leap_cli/ssh_key.rb', line 133

def initialize(rsa_key)
  @key = rsa_key
end

Instance Attribute Details

#commentObject

Returns the value of attribute comment.



15
16
17
# File 'lib/leap_cli/ssh_key.rb', line 15

def comment
  @comment
end

#filenameObject

Returns the value of attribute filename.



14
15
16
# File 'lib/leap_cli/ssh_key.rb', line 14

def filename
  @filename
end

Class Method Details

.load(arg1, arg2 = nil) ⇒ Object

CLASS METHODS



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/leap_cli/ssh_key.rb', line 25

def self.load(arg1, arg2=nil)
  key = nil
  if arg1.is_a? OpenSSL::PKey::RSA
    key = SshKey.new arg1
  elsif arg1.is_a? String
    if arg1 =~ /^ssh-/
      type, data = arg1.split(' ')
      key = SshKey.new load_from_data(data, type)
    elsif File.exists? arg1
      key = SshKey.new load_from_file(arg1)
      key.filename = arg1
    else
      key = SshKey.new load_from_data(arg1, arg2)
    end
  end
  return key
rescue StandardError => exc
end

.load_from_data(data, type = 'ssh-rsa') ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/leap_cli/ssh_key.rb', line 58

def self.load_from_data(data, type='ssh-rsa')
  public_key = nil
  private_key = nil
  begin
    public_key = Net::SSH::KeyFactory.load_data_public_key("#{type} #{data}")
  rescue NotImplementedError, Net::SSH::Exception, OpenSSL::PKey::PKeyError
    begin
      private_key = Net::SSH::KeyFactory.load_data_private_key("#{type} #{data}")
    rescue NotImplementedError, Net::SSH::Exception, OpenSSL::PKey::PKeyError
    end
  end
  public_key || private_key
end

.load_from_file(filename) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/leap_cli/ssh_key.rb', line 44

def self.load_from_file(filename)
  public_key = nil
  private_key = nil
  begin
    public_key = Net::SSH::KeyFactory.load_public_key(filename)
  rescue NotImplementedError, Net::SSH::Exception, OpenSSL::PKey::PKeyError
    begin
      private_key = Net::SSH::KeyFactory.load_private_key(filename)
    rescue NotImplementedError, Net::SSH::Exception, OpenSSL::PKey::PKeyError
    end
  end
  public_key || private_key
end

.parse_keys(string) ⇒ Object

takes a string with one or more ssh keys, one key per line, and returns an array of SshKey objects.

the lines should be in one of these formats:

  1. <hostname> <key-type> <key>

  2. <key-type> <key>



95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/leap_cli/ssh_key.rb', line 95

def self.parse_keys(string)
  keys = []
  lines = string.split("\n").grep(/^[^#]/)
  lines.each do |line|
    if line =~ / #{SshKey::SUPPORTED_TYPES_RE} /
      # <hostname> <key-type> <key>
      keys << line.split(' ')[1..2]
    elsif line =~ /^#{SshKey::SUPPORTED_TYPES_RE} /
      # <key-type> <key>
      keys << line.split(' ')
    end
  end
  return keys.map{|k| SshKey.load(k[1], k[0])}
end

.pick_best_key(keys) ⇒ Object

Picks one key out of an array of keys that we think is the “best”, based on the order of preference in SUPPORTED_TYPES

Currently, this does not take bitsize into account.



78
79
80
81
82
83
84
# File 'lib/leap_cli/ssh_key.rb', line 78

def self.pick_best_key(keys)
  keys.select {|k|
    SUPPORTED_TYPES.include?(k.type)
  }.sort {|a,b|
    SUPPORTED_TYPES.index(a.type) <=> SUPPORTED_TYPES.index(b.type)
  }.first
end

.supported_host_key_algorithms(string) ⇒ Object

takes a string with one or more ssh keys, one key per line, and returns a string that specified the ssh key algorithms that are supported by the keys, in order of preference.

eg: ecdsa-sha2-nistp256,ssh-rsa,ssh-ed25519



117
118
119
120
121
122
123
124
125
# File 'lib/leap_cli/ssh_key.rb', line 117

def self.supported_host_key_algorithms(string)
  if string
    self.parse_keys(string).map {|key|
      key.type
    }.join(',')
  else
    ""
  end
end

Instance Method Details

#==(other_key) ⇒ Object



176
177
178
179
180
# File 'lib/leap_cli/ssh_key.rb', line 176

def ==(other_key)
  return false if other_key.nil?
  return false if self.class != other_key.class
  return self.to_text == other_key.to_text
end

#bitsObject

not sure if this will always work, but is seems to for now.



159
160
161
# File 'lib/leap_cli/ssh_key.rb', line 159

def bits
  Net::SSH::Buffer.from(:key, @key).to_s.split("\001\000").last.size * 8
end

#in_known_hosts?(*identifiers) ⇒ Boolean

Returns:



182
183
184
185
186
187
188
189
# File 'lib/leap_cli/ssh_key.rb', line 182

def in_known_hosts?(*identifiers)
  identifiers.each do |identifier|
    Net::SSH::KnownHosts.search_for(identifier).each do |key|
      return true if self == key
    end
  end
  return false
end

#keyObject



172
173
174
# File 'lib/leap_cli/ssh_key.rb', line 172

def key
  [Net::SSH::Buffer.from(:key, @key).to_s].pack("m*").gsub(/\s/, "")
end

#private_keyObject



152
153
154
# File 'lib/leap_cli/ssh_key.rb', line 152

def private_key
  SshKey.new(@key.private_key)
end

#public_keyObject



148
149
150
# File 'lib/leap_cli/ssh_key.rb', line 148

def public_key
  SshKey.new(@key.public_key)
end

#summaryObject



163
164
165
166
# File 'lib/leap_cli/ssh_key.rb', line 163

def summary
  #"%s %s %s (%s)" % [self.type, self.bits, self.fingerprint, self.filename || self.comment || '']
  "%s %s %s" % [self.type, self.bits, self.fingerprint]
end

#to_sObject



168
169
170
# File 'lib/leap_cli/ssh_key.rb', line 168

def to_s
  self.type + " " + self.key
end