leap_cli 1.8.1 → 1.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|