insert_public_key cap, and use that if it exists

This commit is contained in:
Mitchell Hashimoto 2014-01-03 11:13:21 -08:00
parent 664aaa0088
commit b3a9e6a088
6 changed files with 85 additions and 7 deletions

View File

@ -300,6 +300,12 @@ module Vagrant
end
end
# If we have a private key in our data dir, then use that
data_private_key = @data_dir.join("private_key")
if data_private_key.file?
info[:private_key_path] = [data_private_key.to_s]
end
# Setup the keys
info[:private_key_path] ||= []
if !info[:private_key_path].is_a?(Array)

View File

@ -1,6 +1,7 @@
require 'logger'
require 'pathname'
require 'stringio'
require 'thread'
require 'timeout'
require 'log4r'
@ -27,25 +28,57 @@ module VagrantPlugins
end
def initialize(machine)
@lock = Mutex.new
@machine = machine
@logger = Log4r::Logger.new("vagrant::communication::ssh")
@connection = nil
@inserted_key = false
end
def ready?
@logger.debug("Checking whether SSH is ready...")
# Attempt to connect. This will raise an exception if it fails.
connect
begin
connect
@logger.info("SSH is ready!")
rescue Vagrant::Errors::VagrantError => e
# We catch a `VagrantError` which would signal that something went
# wrong expectedly in the `connect`, which means we didn't connect.
@logger.info("SSH not up: #{e.inspect}")
return false
end
# If we're already attempting to switch out the SSH key, then
# just return that we're ready (for Machine#guest).
@lock.synchronize do
return true if @inserted_key
@inserted_key = true
end
# If we used a password, then insert the insecure key
ssh_info = @machine.ssh_info
if ssh_info[:password] && ssh_info[:private_key_path].empty?
@logger.info("Inserting insecure key to avoid password")
@machine.guest.capability(
:insert_public_key,
Vagrant.source_root.join("keys", "vagrant.pub").read)
# Write out the private key in the data dir so that the
# machine automatically picks it up.
@machine.data_dir.join("private_key").open("w+") do |f|
f.write(Vagrant.source_root.join("keys", "vagrant").read)
end
@logger.info("Disconecting SSH so we can reconnect with new SSH key")
@connection.close
@connection = nil
return ready?
end
# If we reached this point then we successfully connected
@logger.info("SSH is ready!")
true
rescue Vagrant::Errors::VagrantError => e
# We catch a `VagrantError` which would signal that something went
# wrong expectedly in the `connect`, which means we didn't connect.
@logger.info("SSH not up: #{e.inspect}")
return false
end
def execute(command, opts=nil, &block)

View File

@ -0,0 +1,17 @@
module VagrantPlugins
module GuestLinux
module Cap
class InsertPublicKey
def self.insert_public_key(machine, contents)
machine.communicate.tap do |comm|
comm.execute("echo #{contents} > /tmp/key.pub")
comm.execute("mkdir -p ~/.ssh")
comm.execute("chmod 0700 ~/.ssh")
comm.execute("cat /tmp/key.pub >> ~/.ssh/authorized_keys")
comm.execute("chmod 0600 ~/.ssh/authorized_keys")
end
end
end
end
end
end

View File

@ -16,6 +16,11 @@ module VagrantPlugins
Cap::Halt
end
guest_capability("linux", "insert_public_key") do
require_relative "cap/insert_public_key"
Cap::InsertPublicKey
end
guest_capability("linux", "shell_expand_guest_path") do
require_relative "cap/shell_expand_guest_path"
Cap::ShellExpandGuestPath

View File

@ -6,6 +6,7 @@ module VagrantPlugins
attr_accessor :private_key_path
attr_accessor :username
attr_accessor :password
attr_accessor :insert_key
def initialize
@host = UNSET_VALUE
@ -13,6 +14,7 @@ module VagrantPlugins
@private_key_path = UNSET_VALUE
@username = UNSET_VALUE
@password = UNSET_VALUE
@insert_key = UNSET_VALUE
end
def finalize!
@ -21,6 +23,7 @@ module VagrantPlugins
@private_key_path = nil if @private_key_path == UNSET_VALUE
@username = nil if @username == UNSET_VALUE
@password = nil if @password == UNSET_VALUE
@insert_key = true if @insert_key == UNSET_VALUE
if @private_key_path && !@private_key_path.is_a?(Array)
@private_key_path = [@private_key_path]

View File

@ -382,6 +382,20 @@ describe Vagrant::Machine do
expect(instance.ssh_info[:private_key_path]).to be_empty
expect(instance.ssh_info[:password]).to eql("")
end
it "should return the private key in the data dir above all else" do
provider_ssh_info[:private_key_path] = nil
instance.config.ssh.private_key_path = nil
instance.config.ssh.password = ""
instance.data_dir.join("private_key").open("w+") do |f|
f.write("hey")
end
expect(instance.ssh_info[:private_key_path]).to eql(
[instance.data_dir.join("private_key").to_s])
expect(instance.ssh_info[:password]).to eql("")
end
end
end