diff --git a/plugins/guests/windows/cap/public_key.rb b/plugins/guests/windows/cap/public_key.rb index 18e52d1fb..c246bff7d 100644 --- a/plugins/guests/windows/cap/public_key.rb +++ b/plugins/guests/windows/cap/public_key.rb @@ -6,7 +6,12 @@ module VagrantPlugins class PublicKey def self.insert_public_key(machine, contents) if machine.communicate.is_a?(CommunicatorWinSSH::Communicator) - winssh_insert_public_key(machine, contents) + contents = contents.strip + modify_authorized_keys machine do |keys| + if !keys.include?(contents) + keys << contents + end + end else raise Vagrant::Errors::SSHInsertKeyUnsupported end @@ -14,16 +19,16 @@ module VagrantPlugins def self.remove_public_key(machine, contents) if machine.communicate.is_a?(CommunicatorWinSSH::Communicator) - winssh_remove_public_key(machine, contents) + modify_authorized_keys machine do |keys| + keys.delete(contents) + end else raise Vagrant::Errors::SSHInsertKeyUnsupported end end - def self.winssh_insert_public_key(machine, contents) + def self.modify_authorized_keys(machine) comm = machine.communicate - contents = contents.strip - directories = fetch_guest_paths(comm) home_dir = directories[:home] temp_dir = directories[:temp] @@ -40,45 +45,18 @@ module VagrantPlugins result = comm.execute("dir \"#{remote_authkeys_path}\"", shell: "cmd", error_check: false) if result == 0 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") + keys = File.read(keys_file.path).split(/[\r\n]+/) else - File.write(keys_file.path, contents + "\r\n") + keys = [] end + yield keys + File.write(keys_file.path, keys.join("\r\n") + "\r\n") comm.upload(keys_file.path, remote_upload_path) keys_file.delete - comm.execute("Set-Acl \"#{remote_upload_path}\" (Get-Acl \"#{remote_authkeys_path}\")", shell: "powershell") - 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("Set-Acl \"#{remote_upload_path}\" (Get-Acl \"#{remote_authkeys_path}\")", shell: "powershell") - comm.execute("move /y \"#{remote_upload_path}\" \"#{remote_authkeys_path}\"", shell: "cmd") - end + comm.execute <<-EOC.gsub(/^\s*/, ""), shell: "powershell" + Set-Acl "#{remote_upload_path}" (Get-Acl "#{remote_authkeys_path}") + Move-Item -Force "#{remote_upload_path}" "#{remote_authkeys_path}" + EOC end # Fetch user's temporary and home directory paths from the Windows guest diff --git a/test/unit/plugins/guests/windows/cap/insert_public_key_test.rb b/test/unit/plugins/guests/windows/cap/insert_public_key_test.rb index a12373ac8..cacd71fec 100644 --- a/test/unit/plugins/guests/windows/cap/insert_public_key_test.rb +++ b/test/unit/plugins/guests/windows/cap/insert_public_key_test.rb @@ -42,7 +42,6 @@ describe "VagrantPlugins::GuestWindows::Cap::InsertPublicKey" do expect(comm).to receive(:download) expect(comm).to receive(:upload) expect(comm).to receive(:execute).with(/Set-Acl .*/, shell: "powershell") - expect(comm).to receive(:execute).with(/move .*/, shell: "cmd") cap.insert_public_key(machine, "ssh-rsa ...") expect(File.read(@tempfile.path)).to include("ssh-rsa ...") end @@ -58,7 +57,6 @@ describe "VagrantPlugins::GuestWindows::Cap::InsertPublicKey" do expect(comm).to_not receive(:download) expect(comm).to receive(:upload) expect(comm).to receive(:execute).with(/Set-Acl .*/, shell: "powershell") - expect(comm).to receive(:execute).with(/move .*/, shell: "cmd") cap.insert_public_key(machine, "ssh-rsa ...") expect(File.read(@tempfile.path)).to include("ssh-rsa ...") end diff --git a/test/unit/plugins/guests/windows/cap/remove_public_key_test.rb b/test/unit/plugins/guests/windows/cap/remove_public_key_test.rb index e82d26810..d693fd2d3 100644 --- a/test/unit/plugins/guests/windows/cap/remove_public_key_test.rb +++ b/test/unit/plugins/guests/windows/cap/remove_public_key_test.rb @@ -27,6 +27,7 @@ describe "VagrantPlugins::GuestWindows::Cap::RemovePublicKey" do allow(machine).to receive(:communicate).and_return(comm) allow(comm).to receive(:execute).with(/echo .+/, shell: "cmd").and_yield(:stdout, "TEMP\r\nHOME\r\n") + allow(comm).to receive(:execute).with(/dir .+\.ssh/, shell: "cmd") allow(comm).to receive(:execute).with(/dir .+authorized_keys/, shell: "cmd", error_check: false).and_return(auth_keys_check_result) end @@ -48,7 +49,6 @@ describe "VagrantPlugins::GuestWindows::Cap::RemovePublicKey" do expect(comm).to receive(:download) expect(comm).to receive(:upload) expect(comm).to receive(:execute).with(/Set-Acl .*/, shell: "powershell") - expect(comm).to receive(:execute).with(/move .*/, shell: "cmd") cap.remove_public_key(machine, public_key_insecure) expect(File.read(@tempfile.path)).to include(public_key_other) expect(File.read(@tempfile.path)).to_not include(public_key_insecure) @@ -58,9 +58,8 @@ describe "VagrantPlugins::GuestWindows::Cap::RemovePublicKey" do context "when authorized_keys does not exist on guest" do it "does nothing" do expect(comm).to_not receive(:download) - expect(comm).to_not receive(:upload) - expect(comm).to_not receive(:execute).with(/Set-Acl .*/, shell: "powershell") - expect(comm).to_not receive(:execute).with(/move .*/, shell: "cmd") + expect(comm).to receive(:upload) + expect(comm).to receive(:execute).with(/Set-Acl .*/, shell: "powershell") cap.remove_public_key(machine, public_key_insecure) end end