From 0d3979f80d4f1b616a2e89a4595b1af9b1ef9c50 Mon Sep 17 00:00:00 2001 From: Shawn Neal Date: Mon, 19 May 2014 08:04:59 -0700 Subject: [PATCH] Fixed issue 3816 Elevated command line is now rendered to a script which is uploaded to the guest and executed. This allows the command line itself to be less than 100 chars to start the script and any user commands are puts into the script which has unlimited* length. --- plugins/communicators/winrm/communicator.rb | 35 +++++++++++++++---- .../communicators/winrm/communicator_test.rb | 6 ++-- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/plugins/communicators/winrm/communicator.rb b/plugins/communicators/winrm/communicator.rb index bfabd2fb1..b3aea49e4 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) @@ -119,6 +115,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