Merge pull request #10528 from chrisroberts/e-ps-elevated
Add support for running elevated commands using the powershell command
This commit is contained in:
commit
023238b3d1
|
@ -26,6 +26,10 @@ module VagrantPlugins
|
|||
o.on("-c", "--command COMMAND", "Execute a powershell command directly") do |c|
|
||||
options[:command] = c
|
||||
end
|
||||
|
||||
o.on("-e", "--elevated", "Execute a powershell command with elevated permissions") do |c|
|
||||
options[:elevated] = true
|
||||
end
|
||||
end
|
||||
|
||||
# Parse out the extra args to send to the ps session, which
|
||||
|
@ -40,8 +44,8 @@ module VagrantPlugins
|
|||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
|
||||
# Check if the host even supports ps remoting
|
||||
raise Errors::HostUnsupported if !@env.host.capability?(:ps_client)
|
||||
# Elevated option enabled means we can only execute commands
|
||||
raise Errors::ElevatedNoCommand if !options[:command] && options[:elevated]
|
||||
|
||||
# Execute ps session if we can
|
||||
with_target_vms(argv, single_target: true) do |machine|
|
||||
|
@ -49,12 +53,12 @@ module VagrantPlugins
|
|||
raise Vagrant::Errors::VMNotCreatedError
|
||||
end
|
||||
|
||||
if machine.config.vm.communicator != :winrm
|
||||
raise VagrantPlugins::CommunicatorWinRM::Errors::WinRMNotReady
|
||||
end
|
||||
if options[:command]
|
||||
if machine.config.vm.communicator != :winrm
|
||||
raise VagrantPlugins::CommunicatorWinRM::Errors::WinRMNotReady
|
||||
end
|
||||
|
||||
if !options[:command].nil?
|
||||
out_code = machine.communicate.execute(options[:command].dup) do |type,data|
|
||||
out_code = machine.communicate.execute(options[:command].dup, elevated: options[:elevated]) do |type,data|
|
||||
machine.ui.detail(data) if type == :stdout
|
||||
end
|
||||
if out_code == 0
|
||||
|
@ -63,6 +67,9 @@ module VagrantPlugins
|
|||
next
|
||||
end
|
||||
|
||||
# Check if the host even supports ps remoting
|
||||
raise Errors::HostUnsupported if !@env.host.capability?(:ps_client)
|
||||
|
||||
ps_info = VagrantPlugins::CommunicatorWinRM::Helper.winrm_info(machine)
|
||||
ps_info[:username] = machine.config.winrm.username
|
||||
ps_info[:password] = machine.config.winrm.password
|
||||
|
@ -78,7 +85,7 @@ module VagrantPlugins
|
|||
begin
|
||||
@env.host.capability(:ps_client, ps_info)
|
||||
ensure
|
||||
if !result["PreviousTrustedHosts"].nil?
|
||||
if result["PreviousTrustedHosts"]
|
||||
reset_ps_remoting_for(machine, ps_info)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17,6 +17,10 @@ module VagrantPlugins
|
|||
class PowerShellError < PSCommandError
|
||||
error_key(:powershell_error)
|
||||
end
|
||||
|
||||
class ElevatedNoCommand < PSCommandError
|
||||
error_key(:elevated_no_command)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,13 +6,18 @@ en:
|
|||
Resetting WinRM TrustedHosts to their original value.
|
||||
|
||||
errors:
|
||||
elevated_no_command: |-
|
||||
A command must be provided when the --elevated flag is provided for
|
||||
the powershell command. Please provide a command when using the
|
||||
--elevated flag and try again.
|
||||
|
||||
host_unsupported: |-
|
||||
Your host does not support PowerShell. A remote PowerShell connection
|
||||
can only be made from a windows host.
|
||||
|
||||
ps_remoting_undetected: |-
|
||||
Unable to establish a remote PowerShell connection with the guest.
|
||||
Check if the firewall rules on the guest allow connections to the
|
||||
Unable to establish a remote PowerShell connection with the guest.
|
||||
Check if the firewall rules on the guest allow connections to the
|
||||
Windows remote management service.
|
||||
|
||||
powershell_error: |-
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
require File.expand_path("../../../../base", __FILE__)
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/powershell/command")
|
||||
|
||||
describe VagrantPlugins::CommandPS::Command do
|
||||
include_context "unit"
|
||||
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
let(:guest) { double("guest") }
|
||||
let(:host) { double("host") }
|
||||
let(:config) {
|
||||
double("config",
|
||||
vm: double("vm", communicator: communicator_name),
|
||||
winrm: double("winrm", username: winrm_username, password: winrm_password)
|
||||
)
|
||||
}
|
||||
let(:communicator_name) { :winrm }
|
||||
let(:winrm_info) { {host: winrm_host, port: winrm_port} }
|
||||
let(:winrm_username) { double("winrm_username") }
|
||||
let(:winrm_password) { double("winrm_password") }
|
||||
let(:winrm_host) { double("winrm_host") }
|
||||
let(:winrm_port) { double("winrm_port") }
|
||||
|
||||
let(:remoting_ready_result) { {} }
|
||||
|
||||
let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) }
|
||||
|
||||
let(:argv) { [] }
|
||||
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:with_target_vms) { |&block| block.call machine }
|
||||
allow(iso_env).to receive(:host).and_return(host)
|
||||
allow(host).to receive(:capability?).with(:ps_client).and_return(true)
|
||||
|
||||
allow(machine.communicate).to receive(:ready?).and_return(true)
|
||||
allow(machine).to receive(:config).and_return(config)
|
||||
|
||||
allow(VagrantPlugins::CommunicatorWinRM::Helper).to receive(:winrm_info).and_return(winrm_info)
|
||||
allow(subject).to receive(:ready_ps_remoting_for).and_return(remoting_ready_result)
|
||||
allow(host).to receive(:capability).with(:ps_client, any_args)
|
||||
|
||||
# Ignore loading up translations
|
||||
allow_any_instance_of(Vagrant::Errors::VagrantError).to receive(:translate_error)
|
||||
end
|
||||
|
||||
describe "#execute" do
|
||||
context "when communicator is not ready" do
|
||||
before { expect(machine.communicate).to receive(:ready?).and_return(false) }
|
||||
|
||||
it "should raise error that machine is not created" do
|
||||
expect { subject.execute }.to raise_error(Vagrant::Errors::VMNotCreatedError)
|
||||
end
|
||||
end
|
||||
|
||||
context "when communicator is not winrm" do
|
||||
let(:communicator_name) { :ssh }
|
||||
|
||||
context "when command is provided" do
|
||||
let(:argv) { ["-c", "command"] }
|
||||
|
||||
it "should raise an error that winrm is not ready" do
|
||||
expect { subject.execute }.to raise_error(VagrantPlugins::CommunicatorWinRM::Errors::WinRMNotReady)
|
||||
end
|
||||
end
|
||||
|
||||
context "when no command is provided" do
|
||||
it "should create a powershell session" do
|
||||
expect(host).to receive(:capability).with(:ps_client, any_args)
|
||||
subject.execute
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when host does not support ps_client" do
|
||||
before { allow(host).to receive(:capability?).with(:ps_client).and_return(false) }
|
||||
|
||||
context "when no command is provided" do
|
||||
it "should raise an error for unsupported host" do
|
||||
expect { subject.execute }.to raise_error(VagrantPlugins::CommandPS::Errors::HostUnsupported)
|
||||
end
|
||||
end
|
||||
|
||||
context "when command is provided" do
|
||||
let(:argv) { ["-c", "command"] }
|
||||
|
||||
it "should execute command when command is provided" do
|
||||
expect(machine.communicate).to receive(:execute).with("command", any_args).and_return(0)
|
||||
subject.execute
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with command provided" do
|
||||
let(:argv) { ["-c", "command"] }
|
||||
|
||||
it "executes the command on the guest" do
|
||||
expect(machine.communicate).to receive(:execute).with("command", any_args).and_return(0)
|
||||
subject.execute
|
||||
end
|
||||
|
||||
context "with elevated flag" do
|
||||
let(:argv) { ["-e", "-c", "command"] }
|
||||
|
||||
it "should execute the command with elevated option" do
|
||||
expect(machine.communicate).to receive(:execute).
|
||||
with("command", hash_including(elevated: true)).and_return(0)
|
||||
subject.execute
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with elevated flag and no command" do
|
||||
let(:argv) { ["-e"] }
|
||||
|
||||
it "should raise error that command must be provided" do
|
||||
expect { subject.execute }.to raise_error(VagrantPlugins::CommandPS::Errors::ElevatedNoCommand)
|
||||
end
|
||||
end
|
||||
|
||||
it "should start a new session" do
|
||||
expect(host).to receive(:capability).with(:ps_client, any_args)
|
||||
subject.execute
|
||||
end
|
||||
|
||||
context "when setup returns PreviousTrustedHosts" do
|
||||
let(:remoting_ready_result) { {"PreviousTrustedHosts" => true} }
|
||||
|
||||
it "should reset the powershell remoting" do
|
||||
expect(subject).to receive(:reset_ps_remoting_for)
|
||||
subject.execute
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue