107 lines
4.1 KiB
Ruby
107 lines
4.1 KiB
Ruby
require "tempfile"
|
|
|
|
module VagrantPlugins
|
|
module GuestWindows
|
|
module Cap
|
|
class PublicKey
|
|
def self.insert_public_key(machine, contents)
|
|
if machine.communicate.is_a?(CommunicatorWinSSH::Communicator)
|
|
winssh_insert_public_key(machine, contents)
|
|
else
|
|
raise Vagrant::Errors::SSHInsertKeyUnsupported
|
|
end
|
|
end
|
|
|
|
def self.remove_public_key(machine, contents)
|
|
if machine.communicate.is_a?(CommunicatorWinSSH::Communicator)
|
|
winssh_remove_public_key(machine, contents)
|
|
else
|
|
raise Vagrant::Errors::SSHInsertKeyUnsupported
|
|
end
|
|
end
|
|
|
|
def self.winssh_insert_public_key(machine, contents)
|
|
comm = machine.communicate
|
|
contents = contents.strip
|
|
|
|
directories = fetch_guest_paths(comm)
|
|
home_dir = directories[:home]
|
|
temp_dir = directories[:temp]
|
|
|
|
remote_ssh_dir = "#{home_dir}\\.ssh"
|
|
remote_upload_path = "#{temp_dir}\\vagrant-insert-pubkey-#{Time.now.to_i}"
|
|
remote_authkeys_path = "#{remote_ssh_dir}\authorized_keys"
|
|
|
|
# Ensure the user's ssh directory exists
|
|
comm.execute("dir \"#{remote_ssh_dir}\"\n if errorlevel 1 (mkdir \"#{remote_ssh_dir}\")", shell: "cmd")
|
|
remote_upload_path = "#{temp_dir}\\vagrant-insert-pubkey-#{Time.now.to_i}"
|
|
remote_authkeys_path = "#{remote_ssh_dir}\\authorized_keys"
|
|
|
|
keys_file = Tempfile.new("vagrant-windows-insert-public-key")
|
|
# Check if an authorized_keys file already exists
|
|
result = comm.execute("dir \"#{remote_authkeys_path}\"", shell: "cmd", error_check: false)
|
|
if result == 0
|
|
keys_file.close
|
|
comm.download(remote_authkeys_path, keys_file.path)
|
|
current_content = File.read(keys_file.path).split(/[\r\n]+/)
|
|
if !current_content.include?(contents)
|
|
current_content << contents
|
|
end
|
|
File.write(keys_file.path, current_content.join("\r\n") + "\r\n")
|
|
else
|
|
keys_file.puts(contents)
|
|
keys_file.close
|
|
end
|
|
keys_file.delete
|
|
comm.upload(keys_file.path, remote_upload_path)
|
|
comm.execute("move /y \"#{remote_upload_path}\" \"#{remote_authkeys_path}\"", shell: "cmd")
|
|
end
|
|
|
|
def self.winssh_remove_public_key(machine, contents)
|
|
comm = machine.communicate
|
|
|
|
directories = fetch_guest_paths(comm)
|
|
home_dir = directories[:home]
|
|
temp_dir = directories[:temp]
|
|
|
|
remote_ssh_dir = "#{home_dir}\\.ssh"
|
|
remote_upload_path = "#{temp_dir}\\vagrant-remove-pubkey-#{Time.now.to_i}"
|
|
remote_authkeys_path = "#{remote_ssh_dir}\\authorized_keys"
|
|
|
|
# Check if an authorized_keys file already exists
|
|
result = comm.execute("dir \"#{remote_authkeys_path}\"", shell: "cmd", error_check: false)
|
|
if result == 0
|
|
keys_file = Tempfile.new("vagrant-windows-remove-public-key")
|
|
keys_file.close
|
|
comm.download(remote_authkeys_path, keys_file.path)
|
|
current_content = File.read(keys_file.path).split(/[\r\n]+/)
|
|
current_content.delete(contents)
|
|
File.write(keys_file.path, current_content.join("\r\n") + "\r\n")
|
|
comm.upload(keys_file.path, remote_upload_path)
|
|
keys_file.delete
|
|
comm.execute("move /y \"#{remote_upload_path}\" \"#{remote_authkeys_path}\"", shell: "cmd")
|
|
end
|
|
end
|
|
|
|
# Fetch user's temporary and home directory paths from the Windows guest
|
|
#
|
|
# @param [Communicator]
|
|
# @return [Hash] {:temp, :home}
|
|
def self.fetch_guest_paths(communicator)
|
|
output = ""
|
|
communicator.execute("echo %TEMP%\necho %USERPROFILE%", shell: "cmd") do |type, data|
|
|
if type == :stdout
|
|
output << data
|
|
end
|
|
end
|
|
temp_dir, home_dir = output.strip.split(/[\r\n]+/)
|
|
if temp_dir.nil? || home_dir.nil?
|
|
raise Errors::PublicKeyDirectoryFailure
|
|
end
|
|
{temp: temp_dir, home: home_dir}
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|