class WinRM::Shells::Elevated

Runs PowerShell commands elevated via a scheduled task

Attributes

interactive_logon[RW]

@return [Bool] Using an interactive logon

password[RW]

@return [String] The admin user password

username[RW]

@return [String] The admin user name to execute the scheduled task as

Public Class Methods

new(connection_opts, transport, logger) click to toggle source

Create a new elevated shell @param connection_opts [ConnectionOpts] The WinRM connection options @param transport [HttpTransport] The WinRM SOAP transport @param logger [Logger] The logger to log diagnostic messages to

# File lib/winrm/shells/elevated.rb, line 29
def initialize(connection_opts, transport, logger)
  @logger = logger
  @username = connection_opts[:user]
  @password = connection_opts[:password]
  @interactive_logon = false
  @shell = Powershell.new(connection_opts, transport, logger)
  @winrm_file_transporter = WinRM::FS::Core::FileTransporter.new(@shell)
end

Public Instance Methods

close() click to toggle source

Closes the shell if one is open

# File lib/winrm/shells/elevated.rb, line 63
def close
  @shell.close
end
run(command, &block) click to toggle source

Run a command or PowerShell script elevated without any of the restrictions that WinRM puts in place.

@param [String] The command or PS script to wrap in a scheduled task

@return [WinRM::Output] :stdout and :stderr

# File lib/winrm/shells/elevated.rb, line 53
def run(command, &block)
  # if an IO object is passed read it, otherwise assume the contents of the file were passed
  script_text = command.respond_to?(:read) ? command.read : command

  script_path = upload_elevated_shell_script(script_text)
  wrapped_script = wrap_in_scheduled_task(script_path, username, password)
  @shell.run(wrapped_script, &block)
end

Private Instance Methods

elevated_shell_script_content() click to toggle source
# File lib/winrm/shells/elevated.rb, line 89
def elevated_shell_script_content
  IO.read(File.expand_path('../../winrm-elevated/scripts/elevated_shell.ps1', __dir__))
end
upload_elevated_shell_script(script_text) click to toggle source
# File lib/winrm/shells/elevated.rb, line 69
def upload_elevated_shell_script(script_text)
  elevated_shell_path = 'c:/windows/temp/winrm-elevated-shell-' + SecureRandom.uuid + '.ps1'
  with_temp_file(script_text) do |temp_file|
    @winrm_file_transporter.upload(temp_file, elevated_shell_path)
  end
  elevated_shell_path
end
with_temp_file(script_text) { |path| ... } click to toggle source
# File lib/winrm/shells/elevated.rb, line 77
def with_temp_file(script_text)
  file = Tempfile.new(%w[winrm-elevated-shell ps1])
  file.write(script_text)
  file.write("\r\n$Host.SetShouldExit($LASTEXITCODE)")
  file.fsync
  file.close
  yield file.path
ensure
  file.close
  file.unlink
end
wrap_in_scheduled_task(script_path, username, password) click to toggle source
# File lib/winrm/shells/elevated.rb, line 93
def wrap_in_scheduled_task(script_path, username, password)
  context = {
    username: username,
    password: password,
    script_path: script_path,
    interactive_logon: interactive_logon
  }

  b = binding
  locals = context.collect { |k, _| "#{k} = context[#{k.inspect}]; " }
  b.eval(locals.join)
  b.eval(Erubi::Engine.new(elevated_shell_script_content).src)
end