leap_cli 1.8.1 → 1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/leap +6 -12
- data/lib/leap_cli.rb +3 -23
- data/lib/leap_cli/bootstrap.rb +36 -12
- data/lib/leap_cli/commands/common.rb +88 -46
- data/lib/leap_cli/commands/new.rb +24 -17
- data/lib/leap_cli/commands/pre.rb +3 -1
- data/lib/leap_cli/core_ext/hash.rb +19 -0
- data/lib/leap_cli/leapfile.rb +47 -32
- data/lib/leap_cli/log.rb +196 -88
- data/lib/leap_cli/path.rb +5 -5
- data/lib/leap_cli/util.rb +28 -18
- data/lib/leap_cli/version.rb +8 -3
- data/vendor/acme-client/lib/acme-client.rb +1 -0
- data/vendor/acme-client/lib/acme/client.rb +122 -0
- data/vendor/acme-client/lib/acme/client/certificate.rb +30 -0
- data/vendor/acme-client/lib/acme/client/certificate_request.rb +111 -0
- data/vendor/acme-client/lib/acme/client/crypto.rb +98 -0
- data/vendor/acme-client/lib/acme/client/error.rb +16 -0
- data/vendor/acme-client/lib/acme/client/faraday_middleware.rb +123 -0
- data/vendor/acme-client/lib/acme/client/resources.rb +5 -0
- data/vendor/acme-client/lib/acme/client/resources/authorization.rb +44 -0
- data/vendor/acme-client/lib/acme/client/resources/challenges.rb +6 -0
- data/vendor/acme-client/lib/acme/client/resources/challenges/base.rb +43 -0
- data/vendor/acme-client/lib/acme/client/resources/challenges/dns01.rb +19 -0
- data/vendor/acme-client/lib/acme/client/resources/challenges/http01.rb +18 -0
- data/vendor/acme-client/lib/acme/client/resources/challenges/tls_sni01.rb +24 -0
- data/vendor/acme-client/lib/acme/client/resources/registration.rb +37 -0
- data/vendor/acme-client/lib/acme/client/self_sign_certificate.rb +60 -0
- data/vendor/acme-client/lib/acme/client/version.rb +7 -0
- data/vendor/base32/lib/base32.rb +67 -0
- data/vendor/certificate_authority/lib/certificate_authority.rb +2 -1
- data/vendor/certificate_authority/lib/certificate_authority/certificate.rb +4 -4
- data/vendor/certificate_authority/lib/certificate_authority/certificate_revocation_list.rb +7 -5
- data/vendor/certificate_authority/lib/certificate_authority/core_extensions.rb +46 -0
- data/vendor/certificate_authority/lib/certificate_authority/distinguished_name.rb +6 -2
- data/vendor/certificate_authority/lib/certificate_authority/extensions.rb +10 -3
- data/vendor/certificate_authority/lib/certificate_authority/key_material.rb +11 -9
- data/vendor/certificate_authority/lib/certificate_authority/ocsp_handler.rb +3 -3
- data/vendor/certificate_authority/lib/certificate_authority/pkcs11_key_material.rb +0 -2
- data/vendor/certificate_authority/lib/certificate_authority/serial_number.rb +8 -2
- data/vendor/certificate_authority/lib/certificate_authority/validations.rb +31 -0
- data/vendor/rsync_command/lib/rsync_command.rb +49 -12
- metadata +50 -91
- data/lib/leap/platform.rb +0 -90
- data/lib/leap_cli/config/environment.rb +0 -180
- data/lib/leap_cli/config/filter.rb +0 -178
- data/lib/leap_cli/config/manager.rb +0 -419
- data/lib/leap_cli/config/node.rb +0 -77
- data/lib/leap_cli/config/object.rb +0 -428
- data/lib/leap_cli/config/object_list.rb +0 -209
- data/lib/leap_cli/config/provider.rb +0 -22
- data/lib/leap_cli/config/secrets.rb +0 -87
- data/lib/leap_cli/config/sources.rb +0 -11
- data/lib/leap_cli/config/tag.rb +0 -25
- data/lib/leap_cli/lib_ext/capistrano_connections.rb +0 -16
- data/lib/leap_cli/logger.rb +0 -237
- data/lib/leap_cli/remote/leap_plugin.rb +0 -192
- data/lib/leap_cli/remote/puppet_plugin.rb +0 -26
- data/lib/leap_cli/remote/rsync_plugin.rb +0 -35
- data/lib/leap_cli/remote/tasks.rb +0 -51
- data/lib/leap_cli/ssh_key.rb +0 -195
- data/lib/leap_cli/util/remote_command.rb +0 -158
- data/lib/leap_cli/util/secret.rb +0 -55
- data/lib/leap_cli/util/x509.rb +0 -33
@@ -1,192 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# these methods are made available in capistrano tasks as 'leap.method_name'
|
3
|
-
# (see RemoteCommand::new_capistrano)
|
4
|
-
#
|
5
|
-
|
6
|
-
module LeapCli; module Remote; module LeapPlugin
|
7
|
-
|
8
|
-
def required_packages
|
9
|
-
"puppet rsync lsb-release locales"
|
10
|
-
end
|
11
|
-
|
12
|
-
def log(*args, &block)
|
13
|
-
LeapCli::Util::log(*args, &block)
|
14
|
-
end
|
15
|
-
|
16
|
-
#
|
17
|
-
# creates directories that are owned by root and 700 permissions
|
18
|
-
#
|
19
|
-
def mkdirs(*dirs)
|
20
|
-
raise ArgumentError.new('illegal dir name') if dirs.grep(/[\' ]/).any?
|
21
|
-
run dirs.collect{|dir| "mkdir -m 700 -p #{dir}; "}.join
|
22
|
-
end
|
23
|
-
|
24
|
-
#
|
25
|
-
# echos "ok" if the node has been initialized and the required packages are installed, bails out otherwise.
|
26
|
-
#
|
27
|
-
def assert_initialized
|
28
|
-
begin
|
29
|
-
test_initialized_file = "test -f #{Leap::Platform.init_path}"
|
30
|
-
check_required_packages = "! dpkg-query -W --showformat='${Status}\n' #{required_packages} 2>&1 | grep -q -E '(deinstall|no packages)'"
|
31
|
-
run "#{test_initialized_file} && #{check_required_packages} && echo ok"
|
32
|
-
rescue Capistrano::CommandError => exc
|
33
|
-
LeapCli::Util.bail! do
|
34
|
-
exc.hosts.each do |host|
|
35
|
-
node = host.to_s.split('.').first
|
36
|
-
LeapCli::Util.log :error, "running deploy: node not initialized. Run 'leap node init #{node}'", :host => host
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
#
|
43
|
-
# bails out the deploy if the file /etc/leap/no-deploy exists.
|
44
|
-
# This kind of sucks, because it would be better to skip over nodes that have no-deploy set instead
|
45
|
-
# halting the entire deploy. As far as I know, with capistrano, there is no way to close one of the
|
46
|
-
# ssh connections in the pool and make sure it gets no further commands.
|
47
|
-
#
|
48
|
-
def check_for_no_deploy
|
49
|
-
begin
|
50
|
-
run "test ! -f /etc/leap/no-deploy"
|
51
|
-
rescue Capistrano::CommandError => exc
|
52
|
-
LeapCli::Util.bail! do
|
53
|
-
exc.hosts.each do |host|
|
54
|
-
LeapCli::Util.log "Can't continue because file /etc/leap/no-deploy exists", :host => host
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
#
|
61
|
-
# dumps debugging information
|
62
|
-
# #
|
63
|
-
def debug
|
64
|
-
run "#{Leap::Platform.leap_dir}/bin/debug.sh"
|
65
|
-
end
|
66
|
-
|
67
|
-
#
|
68
|
-
# dumps the recent deploy history to the console
|
69
|
-
#
|
70
|
-
def history(lines)
|
71
|
-
command = "(test -s /var/log/leap/deploy-summary.log && tail -n #{lines} /var/log/leap/deploy-summary.log) || (test -s /var/log/leap/deploy-summary.log.1 && tail -n #{lines} /var/log/leap/deploy-summary.log.1) || (echo 'no history')"
|
72
|
-
run command
|
73
|
-
end
|
74
|
-
|
75
|
-
#
|
76
|
-
# This is a hairy ugly hack, exactly the kind of stuff that makes ruby
|
77
|
-
# dangerous and too much fun for its own good.
|
78
|
-
#
|
79
|
-
# In most places, we run remote ssh without a current 'task'. This works fine,
|
80
|
-
# except that in a few places, the behavior of capistrano ssh is controlled by
|
81
|
-
# the options of the current task.
|
82
|
-
#
|
83
|
-
# We don't want to create an actual current task, because tasks are no fun
|
84
|
-
# and can't take arguments or return values. So, when we need to configure
|
85
|
-
# things that can only be configured in a task, we use this handy hack to
|
86
|
-
# fake the current task.
|
87
|
-
#
|
88
|
-
# This is NOT thread safe, but could be made to be so with some extra work.
|
89
|
-
#
|
90
|
-
def with_task(name)
|
91
|
-
task = @config.tasks[name]
|
92
|
-
@config.class.send(:alias_method, :original_current_task, :current_task)
|
93
|
-
@config.class.send(:define_method, :current_task, Proc.new(){ task })
|
94
|
-
begin
|
95
|
-
yield
|
96
|
-
ensure
|
97
|
-
@config.class.send(:remove_method, :current_task)
|
98
|
-
@config.class.send(:alias_method, :current_task, :original_current_task)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
#
|
103
|
-
# similar to run(cmd, &block), but with:
|
104
|
-
#
|
105
|
-
# * exit codes
|
106
|
-
# * stdout and stderr are combined
|
107
|
-
#
|
108
|
-
def stream(cmd, &block)
|
109
|
-
command = '%s 2>&1; echo "exitcode=$?"' % cmd
|
110
|
-
run(command) do |channel, stream, data|
|
111
|
-
exitcode = nil
|
112
|
-
if data =~ /exitcode=(\d+)\n/
|
113
|
-
exitcode = $1.to_i
|
114
|
-
data.sub!(/exitcode=(\d+)\n/,'')
|
115
|
-
end
|
116
|
-
yield({:host => channel[:host], :data => data, :exitcode => exitcode})
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
#
|
121
|
-
# like stream, but capture all the output before returning
|
122
|
-
#
|
123
|
-
def capture(cmd, &block)
|
124
|
-
command = '%s 2>&1; echo "exitcode=$?" 2>&1;' % cmd
|
125
|
-
host_data = {}
|
126
|
-
run(command) do |channel, stream, data|
|
127
|
-
host_data[channel[:host]] ||= ""
|
128
|
-
if data =~ /exitcode=(\d+)\n/
|
129
|
-
exitcode = $1.to_i
|
130
|
-
data.sub!(/exitcode=(\d+)\n/,'')
|
131
|
-
host_data[channel[:host]] += data
|
132
|
-
yield({:host => channel[:host], :data => host_data[channel[:host]], :exitcode => exitcode})
|
133
|
-
else
|
134
|
-
host_data[channel[:host]] += data
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
#
|
140
|
-
# Run a command, with a nice status report and progress indicator.
|
141
|
-
# Only successful results are returned, errors are printed.
|
142
|
-
#
|
143
|
-
# For each successful run on each host, block is yielded with a hash like so:
|
144
|
-
#
|
145
|
-
# {:host => 'bluejay', :exitcode => 0, :data => 'shell output'}
|
146
|
-
#
|
147
|
-
def run_with_progress(cmd, &block)
|
148
|
-
ssh_failures = []
|
149
|
-
exitcode_failures = []
|
150
|
-
succeeded = []
|
151
|
-
task = LeapCli.log_level > 1 ? :standard_task : :skip_errors_task
|
152
|
-
with_task(task) do
|
153
|
-
log :querying, 'facts' do
|
154
|
-
progress " "
|
155
|
-
call_on_failure do |host|
|
156
|
-
ssh_failures << host
|
157
|
-
progress 'F'
|
158
|
-
end
|
159
|
-
capture(cmd) do |response|
|
160
|
-
if response[:exitcode] == 0
|
161
|
-
progress '.'
|
162
|
-
yield response
|
163
|
-
else
|
164
|
-
exitcode_failures << response
|
165
|
-
progress 'F'
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
170
|
-
puts "done"
|
171
|
-
if ssh_failures.any?
|
172
|
-
log :failed, 'to connect to nodes: ' + ssh_failures.join(' ')
|
173
|
-
end
|
174
|
-
if exitcode_failures.any?
|
175
|
-
log :failed, 'to run successfully:' do
|
176
|
-
exitcode_failures.each do |response|
|
177
|
-
log "[%s] exit %s - %s" % [response[:host], response[:exitcode], response[:data].strip]
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
rescue Capistrano::RemoteError => err
|
182
|
-
log :error, err.to_s
|
183
|
-
end
|
184
|
-
|
185
|
-
private
|
186
|
-
|
187
|
-
def progress(str='.')
|
188
|
-
print str
|
189
|
-
STDOUT.flush
|
190
|
-
end
|
191
|
-
|
192
|
-
end; end; end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# these methods are made available in capistrano tasks as 'puppet.method_name'
|
3
|
-
# (see RemoteCommand::new_capistrano)
|
4
|
-
#
|
5
|
-
|
6
|
-
module LeapCli; module Remote; module PuppetPlugin
|
7
|
-
|
8
|
-
def apply(options)
|
9
|
-
run "#{Leap::Platform.leap_dir}/bin/puppet_command set_hostname apply #{flagize(options)}"
|
10
|
-
end
|
11
|
-
|
12
|
-
private
|
13
|
-
|
14
|
-
def flagize(hsh)
|
15
|
-
hsh.inject([]) {|str, item|
|
16
|
-
if item[1] === false
|
17
|
-
str
|
18
|
-
elsif item[1] === true
|
19
|
-
str << "--" + item[0].to_s
|
20
|
-
else
|
21
|
-
str << "--" + item[0].to_s + " " + item[1].inspect
|
22
|
-
end
|
23
|
-
}.join(' ')
|
24
|
-
end
|
25
|
-
|
26
|
-
end; end; end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# these methods are made available in capistrano tasks as 'rsync.method_name'
|
3
|
-
# (see RemoteCommand::new_capistrano)
|
4
|
-
#
|
5
|
-
|
6
|
-
autoload :RsyncCommand, 'rsync_command'
|
7
|
-
|
8
|
-
module LeapCli; module Remote; module RsyncPlugin
|
9
|
-
|
10
|
-
#
|
11
|
-
# takes a block, yielded a server, that should return a hash with various rsync options.
|
12
|
-
# supported options include:
|
13
|
-
#
|
14
|
-
# {:source => '', :dest => '', :flags => '', :includes => [], :excludes => []}
|
15
|
-
#
|
16
|
-
def update
|
17
|
-
rsync = RsyncCommand.new(:logger => logger)
|
18
|
-
rsync.asynchronously(find_servers) do |server|
|
19
|
-
options = yield server
|
20
|
-
next unless options
|
21
|
-
remote_user = server.user || fetch(:user, ENV['USER'])
|
22
|
-
src = options[:source]
|
23
|
-
dest = {:user => remote_user, :host => server.host, :path => options[:dest]}
|
24
|
-
options[:ssh] = ssh_options.merge(server.options[:ssh_options]||{})
|
25
|
-
options[:chdir] ||= Path.provider
|
26
|
-
rsync.exec(src, dest, options)
|
27
|
-
end
|
28
|
-
if rsync.failed?
|
29
|
-
LeapCli::Util.bail! do
|
30
|
-
LeapCli::Util.log :failed, "to rsync to #{rsync.failures.map{|f|f[:dest][:host]}.join(' ')}"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
end; end; end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# This file is evaluated just the same as a typical capistrano "deploy.rb"
|
3
|
-
# For DSL manual, see https://github.com/capistrano/capistrano/wiki
|
4
|
-
#
|
5
|
-
|
6
|
-
MAX_HOSTS = 10
|
7
|
-
|
8
|
-
task :install_authorized_keys, :max_hosts => MAX_HOSTS do
|
9
|
-
leap.log :updating, "authorized_keys" do
|
10
|
-
leap.mkdirs '/root/.ssh'
|
11
|
-
upload LeapCli::Path.named_path(:authorized_keys), '/root/.ssh/authorized_keys', :mode => '600'
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
#
|
16
|
-
# for vagrant nodes, we install insecure vagrant key to authorized_keys2, since deploy
|
17
|
-
# will overwrite authorized_keys.
|
18
|
-
#
|
19
|
-
# why force the insecure vagrant key?
|
20
|
-
# if we don't do this, then first time initialization might fail if the user has many keys
|
21
|
-
# (ssh will bomb out before it gets to the vagrant key).
|
22
|
-
# and it really doesn't make sense to ask users to pin the insecure vagrant key in their
|
23
|
-
# .ssh/config files.
|
24
|
-
#
|
25
|
-
task :install_insecure_vagrant_key, :max_hosts => MAX_HOSTS do
|
26
|
-
leap.log :installing, "insecure vagrant key" do
|
27
|
-
leap.mkdirs '/root/.ssh'
|
28
|
-
upload LeapCli::Path.vagrant_ssh_pub_key_file, '/root/.ssh/authorized_keys2', :mode => '600'
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
task :install_prerequisites, :max_hosts => MAX_HOSTS do
|
33
|
-
bin_dir = File.join(Leap::Platform.leap_dir, 'bin')
|
34
|
-
node_init_path = File.join(bin_dir, 'node_init')
|
35
|
-
|
36
|
-
leap.log :running, "node_init script" do
|
37
|
-
leap.mkdirs bin_dir
|
38
|
-
upload LeapCli::Path.node_init_script, node_init_path, :mode => '500'
|
39
|
-
run node_init_path
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
#
|
44
|
-
# just dummies, used to capture task options
|
45
|
-
#
|
46
|
-
|
47
|
-
task :skip_errors_task, :on_error => :continue, :max_hosts => MAX_HOSTS do
|
48
|
-
end
|
49
|
-
|
50
|
-
task :standard_task, :max_hosts => MAX_HOSTS do
|
51
|
-
end
|
data/lib/leap_cli/ssh_key.rb
DELETED
@@ -1,195 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# A wrapper around OpenSSL::PKey::RSA instances to provide a better api for dealing with SSH keys.
|
3
|
-
#
|
4
|
-
# cipher 'ssh-ed25519' not supported yet because we are waiting for support in Net::SSH
|
5
|
-
#
|
6
|
-
|
7
|
-
require 'net/ssh'
|
8
|
-
require 'forwardable'
|
9
|
-
|
10
|
-
module LeapCli
|
11
|
-
class SshKey
|
12
|
-
extend Forwardable
|
13
|
-
|
14
|
-
attr_accessor :filename
|
15
|
-
attr_accessor :comment
|
16
|
-
|
17
|
-
# supported ssh key types, in order of preference
|
18
|
-
SUPPORTED_TYPES = ['ssh-rsa', 'ecdsa-sha2-nistp256']
|
19
|
-
SUPPORTED_TYPES_RE = /(#{SUPPORTED_TYPES.join('|')})/
|
20
|
-
|
21
|
-
##
|
22
|
-
## CLASS METHODS
|
23
|
-
##
|
24
|
-
|
25
|
-
def self.load(arg1, arg2=nil)
|
26
|
-
key = nil
|
27
|
-
if arg1.is_a? OpenSSL::PKey::RSA
|
28
|
-
key = SshKey.new arg1
|
29
|
-
elsif arg1.is_a? String
|
30
|
-
if arg1 =~ /^ssh-/
|
31
|
-
type, data = arg1.split(' ')
|
32
|
-
key = SshKey.new load_from_data(data, type)
|
33
|
-
elsif File.exists? arg1
|
34
|
-
key = SshKey.new load_from_file(arg1)
|
35
|
-
key.filename = arg1
|
36
|
-
else
|
37
|
-
key = SshKey.new load_from_data(arg1, arg2)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
return key
|
41
|
-
rescue StandardError => exc
|
42
|
-
end
|
43
|
-
|
44
|
-
def self.load_from_file(filename)
|
45
|
-
public_key = nil
|
46
|
-
private_key = nil
|
47
|
-
begin
|
48
|
-
public_key = Net::SSH::KeyFactory.load_public_key(filename)
|
49
|
-
rescue NotImplementedError, Net::SSH::Exception, OpenSSL::PKey::PKeyError
|
50
|
-
begin
|
51
|
-
private_key = Net::SSH::KeyFactory.load_private_key(filename)
|
52
|
-
rescue NotImplementedError, Net::SSH::Exception, OpenSSL::PKey::PKeyError
|
53
|
-
end
|
54
|
-
end
|
55
|
-
public_key || private_key
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.load_from_data(data, type='ssh-rsa')
|
59
|
-
public_key = nil
|
60
|
-
private_key = nil
|
61
|
-
begin
|
62
|
-
public_key = Net::SSH::KeyFactory.load_data_public_key("#{type} #{data}")
|
63
|
-
rescue NotImplementedError, Net::SSH::Exception, OpenSSL::PKey::PKeyError
|
64
|
-
begin
|
65
|
-
private_key = Net::SSH::KeyFactory.load_data_private_key("#{type} #{data}")
|
66
|
-
rescue NotImplementedError, Net::SSH::Exception, OpenSSL::PKey::PKeyError
|
67
|
-
end
|
68
|
-
end
|
69
|
-
public_key || private_key
|
70
|
-
end
|
71
|
-
|
72
|
-
#
|
73
|
-
# Picks one key out of an array of keys that we think is the "best",
|
74
|
-
# based on the order of preference in SUPPORTED_TYPES
|
75
|
-
#
|
76
|
-
# Currently, this does not take bitsize into account.
|
77
|
-
#
|
78
|
-
def self.pick_best_key(keys)
|
79
|
-
keys.select {|k|
|
80
|
-
SUPPORTED_TYPES.include?(k.type)
|
81
|
-
}.sort {|a,b|
|
82
|
-
SUPPORTED_TYPES.index(a.type) <=> SUPPORTED_TYPES.index(b.type)
|
83
|
-
}.first
|
84
|
-
end
|
85
|
-
|
86
|
-
#
|
87
|
-
# takes a string with one or more ssh keys, one key per line,
|
88
|
-
# and returns an array of SshKey objects.
|
89
|
-
#
|
90
|
-
# the lines should be in one of these formats:
|
91
|
-
#
|
92
|
-
# 1. <hostname> <key-type> <key>
|
93
|
-
# 2. <key-type> <key>
|
94
|
-
#
|
95
|
-
def self.parse_keys(string)
|
96
|
-
keys = []
|
97
|
-
lines = string.split("\n").grep(/^[^#]/)
|
98
|
-
lines.each do |line|
|
99
|
-
if line =~ / #{SshKey::SUPPORTED_TYPES_RE} /
|
100
|
-
# <hostname> <key-type> <key>
|
101
|
-
keys << line.split(' ')[1..2]
|
102
|
-
elsif line =~ /^#{SshKey::SUPPORTED_TYPES_RE} /
|
103
|
-
# <key-type> <key>
|
104
|
-
keys << line.split(' ')
|
105
|
-
end
|
106
|
-
end
|
107
|
-
return keys.map{|k| SshKey.load(k[1], k[0])}
|
108
|
-
end
|
109
|
-
|
110
|
-
#
|
111
|
-
# takes a string with one or more ssh keys, one key per line,
|
112
|
-
# and returns a string that specified the ssh key algorithms
|
113
|
-
# that are supported by the keys, in order of preference.
|
114
|
-
#
|
115
|
-
# eg: ecdsa-sha2-nistp256,ssh-rsa,ssh-ed25519
|
116
|
-
#
|
117
|
-
def self.supported_host_key_algorithms(string)
|
118
|
-
if string
|
119
|
-
self.parse_keys(string).map {|key|
|
120
|
-
key.type
|
121
|
-
}.join(',')
|
122
|
-
else
|
123
|
-
""
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
##
|
128
|
-
## INSTANCE METHODS
|
129
|
-
##
|
130
|
-
|
131
|
-
public
|
132
|
-
|
133
|
-
def initialize(rsa_key)
|
134
|
-
@key = rsa_key
|
135
|
-
end
|
136
|
-
|
137
|
-
def_delegator :@key, :fingerprint, :fingerprint
|
138
|
-
def_delegator :@key, :public?, :public?
|
139
|
-
def_delegator :@key, :private?, :private?
|
140
|
-
def_delegator :@key, :ssh_type, :type
|
141
|
-
def_delegator :@key, :public_encrypt, :public_encrypt
|
142
|
-
def_delegator :@key, :public_decrypt, :public_decrypt
|
143
|
-
def_delegator :@key, :private_encrypt, :private_encrypt
|
144
|
-
def_delegator :@key, :private_decrypt, :private_decrypt
|
145
|
-
def_delegator :@key, :params, :params
|
146
|
-
def_delegator :@key, :to_text, :to_text
|
147
|
-
|
148
|
-
def public_key
|
149
|
-
SshKey.new(@key.public_key)
|
150
|
-
end
|
151
|
-
|
152
|
-
def private_key
|
153
|
-
SshKey.new(@key.private_key)
|
154
|
-
end
|
155
|
-
|
156
|
-
#
|
157
|
-
# not sure if this will always work, but is seems to for now.
|
158
|
-
#
|
159
|
-
def bits
|
160
|
-
Net::SSH::Buffer.from(:key, @key).to_s.split("\001\000").last.size * 8
|
161
|
-
end
|
162
|
-
|
163
|
-
def summary
|
164
|
-
if self.filename
|
165
|
-
"%s %s %s (%s)" % [self.type, self.bits, self.fingerprint, File.basename(self.filename)]
|
166
|
-
else
|
167
|
-
"%s %s %s" % [self.type, self.bits, self.fingerprint]
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
def to_s
|
172
|
-
self.type + " " + self.key
|
173
|
-
end
|
174
|
-
|
175
|
-
def key
|
176
|
-
[Net::SSH::Buffer.from(:key, @key).to_s].pack("m*").gsub(/\s/, "")
|
177
|
-
end
|
178
|
-
|
179
|
-
def ==(other_key)
|
180
|
-
return false if other_key.nil?
|
181
|
-
return false if self.class != other_key.class
|
182
|
-
return self.to_text == other_key.to_text
|
183
|
-
end
|
184
|
-
|
185
|
-
def in_known_hosts?(*identifiers)
|
186
|
-
identifiers.each do |identifier|
|
187
|
-
Net::SSH::KnownHosts.search_for(identifier).each do |key|
|
188
|
-
return true if self == key
|
189
|
-
end
|
190
|
-
end
|
191
|
-
return false
|
192
|
-
end
|
193
|
-
|
194
|
-
end
|
195
|
-
end
|