diff --git a/plugins/communicators/winrm/communicator.rb b/plugins/communicators/winrm/communicator.rb index 839061e26..37ce216fa 100644 --- a/plugins/communicators/winrm/communicator.rb +++ b/plugins/communicators/winrm/communicator.rb @@ -69,12 +69,8 @@ module VagrantPlugins opts[:good_exit] = Array(opts[:good_exit]) if opts[:elevated] - path = File.expand_path("../scripts/elevated_shell.ps1", __FILE__) - command = Vagrant::Util::TemplateRenderer.render(path, options: { - username: shell.username, - password: shell.password, - command: command, - }) + guest_script_path = create_elevated_shell_script(command) + command = "powershell -executionpolicy bypass -file #{guest_script_path}" end output = shell.send(opts[:shell], command, &block) @@ -120,6 +116,33 @@ module VagrantPlugins ) end + # Creates and uploads a PowerShell script which wraps the specified + # command in a scheduled task. The scheduled task allows commands to + # run on the guest as a true local admin without any of the restrictions + # that WinRM puts in place. + # + # @return The path to elevated_shell.ps1 on the guest + def create_elevated_shell_script(command) + path = File.expand_path("../scripts/elevated_shell.ps1", __FILE__) + script = Vagrant::Util::TemplateRenderer.render(path, options: { + username: shell.username, + password: shell.password, + command: command, + }) + guest_script_path = "c:/tmp/vagrant-elevated-shell.ps1" + file = Tempfile.new(["vagrant-elevated-shell", "ps1"]) + begin + file.write(script) + file.fsync + file.close + upload(file.path, guest_script_path) + ensure + file.close + file.unlink + end + guest_script_path + end + # Handles the raw WinRM shell result and converts it to a # standard Vagrant communicator result def execution_output(output, opts) diff --git a/test/unit/plugins/communicators/winrm/communicator_test.rb b/test/unit/plugins/communicators/winrm/communicator_test.rb index d6013be7c..c2a8c8139 100644 --- a/test/unit/plugins/communicators/winrm/communicator_test.rb +++ b/test/unit/plugins/communicators/winrm/communicator_test.rb @@ -48,11 +48,9 @@ describe VagrantPlugins::CommunicatorWinRM::Communicator do end it "wraps command in elevated shell script when elevated is true" do + expect(shell).to receive(:upload).with(kind_of(String), "c:/tmp/vagrant-elevated-shell.ps1") expect(shell).to receive(:powershell) do |cmd| - expect(cmd).to include("$command = \"dir\"") - expect(cmd).to include("$user = 'vagrant'") - expect(cmd).to include("$password = 'password'") - expect(cmd).to include("New-Object -ComObject \"Schedule.Service\"") + expect(cmd).to eq("powershell -executionpolicy bypass -file c:/tmp/vagrant-elevated-shell.ps1") end.and_return({ exitcode: 0 }) expect(subject.execute("dir", { elevated: true })).to eq(0) end