From a269255b2f51783ba19cbc363759ba9a61038ea0 Mon Sep 17 00:00:00 2001 From: elijah Date: Thu, 25 Oct 2012 00:49:10 -0700 Subject: cleaned up the code a bit by adding SshKey class. --- lib/leap_cli/commands/node.rb | 79 +++++++------------------------------------ 1 file changed, 13 insertions(+), 66 deletions(-) (limited to 'lib/leap_cli/commands/node.rb') diff --git a/lib/leap_cli/commands/node.rb b/lib/leap_cli/commands/node.rb index 46c8fb6..b9640a8 100644 --- a/lib/leap_cli/commands/node.rb +++ b/lib/leap_cli/commands/node.rb @@ -7,11 +7,11 @@ module LeapCli; module Commands ## COMMANDS ## - #desc 'Create a new configuration for a node' - #command :'new-node' do |c| - # c.action do |global_options,options,args| - # end - #end + desc 'not yet implemented... Create a new configuration for a node' + command :'new-node' do |c| + c.action do |global_options,options,args| + end + end desc 'Bootstraps a node, setting up ssh keys and installing prerequisites' arg_name '', :optional => false, :multiple => false @@ -84,28 +84,27 @@ module LeapCli; module Commands # def save_public_host_key(node) progress("Fetching public SSH host key for #{node.name}") - public_key, key_type = get_public_key_for_ip(node.ip_address) + public_key = get_public_key_for_ip(node.ip_address) pub_key_path = Path.named_path([:node_ssh_pub_key, node.name]) if Path.exists?(pub_key_path) - if file_content_equals?(pub_key_path, node_pub_key_contents(key_type, public_key)) + if public_key == SshKey.load_from_file(pub_key_path) progress("Public SSH host key for #{node.name} has not changed") else bail!("WARNING: The public SSH host key we just fetched for #{node.name} doesn't match what we have saved previously. Remove the file #{pub_key_path} if you really want to change it.") end - elsif key_in_known_hosts?(public_key, [node.name, node.ip_address, node.domain.name]) + elsif public_key.in_known_hosts?(node.name, node.ip_address, node.domain.name) progress("Public SSH host key for #{node.name} is trusted (key found in your ~/.ssh/known_hosts)") else - fingerprint, bits = ssh_key_fingerprint(key_type, public_key) puts say("This is the SSH host key you got back from node \"#{node.name}\"") - say("Type -- #{bits} bit #{key_type.upcase}") - say("Fingerprint -- " + fingerprint) - say("Public Key -- " + public_key) + say("Type -- #{public_key.bits} bit #{public_key.type.upcase}") + say("Fingerprint -- " + public_key.fingerprint) + say("Public Key -- " + public_key.key) if !agree("Is this correct? ") bail! else puts - write_file!([:node_ssh_pub_key, node.name], node_pub_key_contents(key_type, public_key)) + write_file!([:node_ssh_pub_key, node.name], public_key.to_s) end end end @@ -116,49 +115,7 @@ module LeapCli; module Commands line = output.split("\n").grep(/^[^#]/).first assert! line, "Got zero host keys back!" ip, key_type, public_key = line.split(' ') - return [public_key, key_type] - end - - # - # returns true if the particular host_key is found in a "known_hosts" file installed for the current user or on this machine. - # - # - host_key: string of ssh public host key - # - identifiers: an array of identifers (which could be an ip address or hostname) - # - def key_in_known_hosts?(host_key, identifiers) - identifiers.each do |identifier| - Net::SSH::KnownHosts.search_for(identifier).each do |key| - # i am not sure what format ssh keys are in, but key.to_pem returns something different than we need. - # this little bit of magic code will encode correctly. I think the format is base64 encoding of bits, exponent, and modulus. - key_string = [Net::SSH::Buffer.from(:key, key).to_s].pack("m*").gsub(/\s/, "") - return true if key_string == host_key - end - end - return false - end - - # - # gets a fingerprint for a key string - # - # i think this could better be done this way: - # blob = Net::SSH::Buffer.from(:key, key).to_s - # fingerprint = OpenSSL::Digest::MD5.hexdigest(blob).scan(/../).join(":") - # - def ssh_key_fingerprint(type, key) - assert_bin!('ssh-keygen') - file = Tempfile.new('leap_cli_public_key_') - begin - file.write(type) - file.write(" ") - file.write(key) - file.close - output = assert_run!("ssh-keygen -l -f #{file.path}", "Failed to run ssh-keygen on public key.") - bits, fingerprint, filename, key_type = output.split(' ') - return [fingerprint, bits] - ensure - file.close - file.unlink - end + return SshKey.load(public_key, key_type) end def ping_node(node) @@ -166,14 +123,4 @@ module LeapCli; module Commands assert_run!("ping -W 1 -c 1 #{node.ip_address}", "Could not ping #{node.name} (address #{node.ip_address}). Try again, we only send a single ping.") end - # - # returns a string that can be used for the contents of the files/nodes/x/x_ssh_key.pub file - # - # We write the file without ipaddress or hostname, because these might change later. - # The ip and host is added at when compiling the combined known_hosts file. - # - def node_pub_key_contents(key_type, public_key) - [key_type, public_key].join(' ') - end - end; end \ No newline at end of file -- cgit v1.2.3