winrm-elevated 1.1.1 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e4eafa3868086d590ce41b1b34631f82a2830d62ce635423cc17a7137ee82fe1
4
- data.tar.gz: 9e673bfbbbf91f8c3595b4ad2680d61bc12fe423bf2ff65c0a47196459fd9a12
3
+ metadata.gz: ee0adbdb22c257558248a863ab41505ef63bbe664150084be3cd57ecc56eef3e
4
+ data.tar.gz: d3442d4883f6617827977d6c2538f8d4961a1bf45de3e45be4c249e34ec548c3
5
5
  SHA512:
6
- metadata.gz: 15871834756bd792d2df264a426d8f3c4aa76cb083a279beeabccf8ffe2693413910ac59447dba6639201904bd5cd03e8b2ce4adb9263a27aab9a20b84bab56e
7
- data.tar.gz: 7648a7e4337a7b7f89e082725a96e1fe7764e5923053b18b4cb13b9eb62f378f1fd9b8db147c84b122e41b26a1ab988940c5cef567a26fbbfc054890170d9566
6
+ metadata.gz: 439dfd36cc9777886088dccb8172885844f319f3e808fb951b2eac31e115367e500f97b9d6fc2d0006588a7c1a8bedbb034d8af1678bc6d39d10647c6db2a958
7
+ data.tar.gz: 63935500fcb295b1359c2222cb1860788fbb2f7859c2f303c8928b61b478197c72e4fa2163070873e333e45d822a7164ea365947cdb5b7c3a6ca117ff20bdbc5
@@ -13,5 +13,5 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require 'winrm'
16
+ require 'winrm' unless defined?(WinRM::Connection)
17
17
  require_relative 'winrm/shells/elevated'
@@ -16,7 +16,7 @@ if($interactive -eq 'true') {
16
16
  $logon_type_xml = "<LogonType>InteractiveTokenOrPassword</LogonType>"
17
17
  }
18
18
 
19
- $task_name = "WinRM_Elevated_Shell"
19
+ $task_name = "WinRM_Elevated_Shell_" + [guid]::NewGuid()
20
20
  $out_file = [System.IO.Path]::GetTempFileName()
21
21
  $err_file = [System.IO.Path]::GetTempFileName()
22
22
 
@@ -64,44 +64,65 @@ $task_xml = $task_xml.Replace("{arguments}", $arguments)
64
64
  $task_xml = $task_xml.Replace("{username}", $username)
65
65
  $task_xml = $task_xml.Replace("{logon_type}", $logon_type_xml)
66
66
 
67
- $schedule = New-Object -ComObject "Schedule.Service"
68
- $schedule.Connect()
69
- $task = $schedule.NewTask($null)
70
- $task.XmlText = $task_xml
71
- $folder = $schedule.GetFolder("\")
72
- $folder.RegisterTaskDefinition($task_name, $task, 6, $username, $pass_to_use, $logon_type, $null) | Out-Null
67
+ try {
68
+ $schedule = New-Object -ComObject "Schedule.Service"
69
+ $schedule.Connect()
70
+ $task = $schedule.NewTask($null)
71
+ $task.XmlText = $task_xml
72
+ $folder = $schedule.GetFolder("\")
73
+ $folder.RegisterTaskDefinition($task_name, $task, 6, $username, $pass_to_use, $logon_type, $null) | Out-Null
73
74
 
74
- $registered_task = $folder.GetTask("\$task_name")
75
- $registered_task.Run($null) | Out-Null
75
+ $registered_task = $folder.GetTask("\$task_name")
76
+ $registered_task.Run($null) | Out-Null
76
77
 
77
- $timeout = 10
78
- $sec = 0
79
- while ( (!($registered_task.state -eq 4)) -and ($sec -lt $timeout) ) {
80
- Start-Sleep -s 1
81
- $sec++
78
+ $timeout = 10
79
+ $sec = 0
80
+ while ( (!($registered_task.state -eq 4)) -and ($sec -lt $timeout) ) {
81
+ Start-Sleep -s 1
82
+ $sec++
83
+ }
84
+ } catch {
85
+ Write-Error -ErrorRecord $PSItem
86
+ exit $PSItem.Exception.HResult
82
87
  }
83
88
 
84
89
  function SlurpOutput($file, $cur_line, $out_type) {
85
90
  if (Test-Path $file) {
86
- get-content $file | select -skip $cur_line | ForEach {
87
- $cur_line += 1
88
- if ($out_type -eq 'err') {
89
- $host.ui.WriteErrorLine("$_")
90
- } else {
91
- $host.ui.WriteLine("$_")
91
+ $fs = New-Object -TypeName System.IO.FileStream -ArgumentList @(
92
+ $file,
93
+ [system.io.filemode]::Open,
94
+ [System.io.FileAccess]::Read,
95
+ [System.IO.FileShare]::ReadWrite
96
+ )
97
+ try {
98
+ $enc = [System.Text.Encoding]::GetEncoding($Host.CurrentCulture.TextInfo.OEMCodePage)
99
+ $bytes = [System.Byte[]]::CreateInstance([System.Byte], $fs.Length)
100
+ if ($fs.Read($bytes, 0, $fs.Length) -gt 0) {
101
+ $text = $enc.GetString($bytes)
102
+ $text.TrimEnd("`n").TrimEnd("`r").Split(@("`r`n", "`n"), [StringSplitOptions]::None) | Select-Object -skip $cur_line | ForEach-Object {
103
+ $cur_line += 1
104
+ if ($out_type -eq 'err') {
105
+ $host.ui.WriteErrorLine("$_")
106
+ } else {
107
+ $host.ui.WriteLine("$_")
108
+ }
109
+ }
92
110
  }
93
111
  }
112
+ finally { $fs.Close() }
94
113
  }
95
114
  return $cur_line
96
115
  }
97
116
 
98
117
  $err_cur_line = 0
99
118
  $out_cur_line = 0
119
+ $timeout = <%= execution_timeout %>
120
+ $startDate = Get-Date
100
121
  do {
101
122
  Start-Sleep -m 100
102
123
  $out_cur_line = SlurpOutput $out_file $out_cur_line 'out'
103
124
  $err_cur_line = SlurpOutput $err_file $err_cur_line 'err'
104
- } while (!($registered_task.state -eq 3))
125
+ } while( (!($registered_task.state -eq 3)) -and ($startDate.AddSeconds($timeout) -gt (Get-Date)) )
105
126
 
106
127
  # We'll make a best effort to clean these files
107
128
  # But a reboot could possibly end the task while the process
@@ -111,6 +132,19 @@ try { Remove-Item $err_file -ErrorAction Stop } catch {}
111
132
  try { Remove-Item $script_file -ErrorAction Stop } catch {}
112
133
 
113
134
  $exit_code = $registered_task.LastTaskResult
135
+
136
+ try {
137
+ # Clean current task
138
+ $folder.DeleteTask($task_name, 0)
139
+ # Clean old tasks if required
140
+ $old_tasks_filter_date = [datetime]::Now.AddSeconds(<%= -1 * execution_timeout %>)
141
+ $old_tasks_to_kill = $folder.GetTasks(0) | Select Name,LastRunTime | Where-Object {
142
+ ($_.Name -like "WinRM_Elevated_Shell*") -and ($_.LastRunTime -le $old_tasks_filter_date) -and ($_.Name -ne $task_name)
143
+ }
144
+ $old_tasks_to_kill | ForEach-Object { try { $folder.DeleteTask($_.Name, 0) } catch {} }
145
+ }
146
+ catch {}
147
+
114
148
  [System.Runtime.Interopservices.Marshal]::ReleaseComObject($schedule) | Out-Null
115
149
 
116
150
  exit $exit_code
@@ -13,10 +13,11 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require 'erubis'
17
- require 'winrm'
16
+ require 'erubi'
17
+ require 'winrm' unless defined?(WinRM::Connection)
18
18
  require 'winrm-fs'
19
- require 'securerandom'
19
+ require 'securerandom' unless defined?(SecureRandom)
20
+ require 'stringio'
20
21
 
21
22
  module WinRM
22
23
  module Shells
@@ -33,6 +34,7 @@ module WinRM
33
34
  @interactive_logon = false
34
35
  @shell = Powershell.new(connection_opts, transport, logger)
35
36
  @winrm_file_transporter = WinRM::FS::Core::FileTransporter.new(@shell)
37
+ @execution_timeout = 86_400
36
38
  end
37
39
 
38
40
  # @return [String] The admin user name to execute the scheduled task as
@@ -44,6 +46,9 @@ module WinRM
44
46
  # @return [Bool] Using an interactive logon
45
47
  attr_accessor :interactive_logon
46
48
 
49
+ # @return [Integer] Timeout for the task to be executed
50
+ attr_accessor :execution_timeout
51
+
47
52
  # Run a command or PowerShell script elevated without any of the
48
53
  # restrictions that WinRM puts in place.
49
54
  #
@@ -68,35 +73,30 @@ module WinRM
68
73
 
69
74
  def upload_elevated_shell_script(script_text)
70
75
  elevated_shell_path = 'c:/windows/temp/winrm-elevated-shell-' + SecureRandom.uuid + '.ps1'
71
- with_temp_file(script_text) do |temp_file|
72
- @winrm_file_transporter.upload(temp_file, elevated_shell_path)
73
- end
76
+ # Prepend the content of the file with an UTF-8 BOM for Windows to read it as such instead of the default
77
+ # Windows-XXXX encoding, and convert script_text accordingly if needed.
78
+ script_text_with_exit = "\uFEFF#{script_text.encode(Encoding::UTF_8)}\r\n$Host.SetShouldExit($LASTEXITCODE)"
79
+ @winrm_file_transporter.upload(StringIO.new(script_text_with_exit), elevated_shell_path)
74
80
  elevated_shell_path
75
81
  end
76
82
 
77
- def with_temp_file(script_text)
78
- file = Tempfile.new(['winrm-elevated-shell', 'ps1'])
79
- file.write(script_text)
80
- file.write("\r\n$Host.SetShouldExit($LASTEXITCODE)")
81
- file.fsync
82
- file.close
83
- yield file.path
84
- ensure
85
- file.close
86
- file.unlink
87
- end
88
-
89
83
  def elevated_shell_script_content
90
84
  IO.read(File.expand_path('../../winrm-elevated/scripts/elevated_shell.ps1', __dir__))
91
85
  end
92
86
 
93
87
  def wrap_in_scheduled_task(script_path, username, password)
94
- Erubis::Eruby.new(elevated_shell_script_content).result(
88
+ context = {
95
89
  username: username,
96
90
  password: password,
97
91
  script_path: script_path,
98
- interactive_logon: interactive_logon
99
- )
92
+ interactive_logon: interactive_logon,
93
+ execution_timeout: execution_timeout
94
+ }
95
+
96
+ b = binding
97
+ locals = context.collect { |k, _| "#{k} = context[#{k.inspect}]; " }
98
+ b.eval(locals.join)
99
+ b.eval(Erubi::Engine.new(elevated_shell_script_content).src)
100
100
  end
101
101
  end
102
102
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: winrm-elevated
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shawn Neal
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-19 00:00:00.000000000 Z
11
+ date: 2020-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: erubi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: winrm
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -113,15 +127,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
113
127
  requirements:
114
128
  - - ">="
115
129
  - !ruby/object:Gem::Version
116
- version: 2.2.0
130
+ version: 2.3.0
117
131
  required_rubygems_version: !ruby/object:Gem::Requirement
118
132
  requirements:
119
133
  - - ">="
120
134
  - !ruby/object:Gem::Version
121
135
  version: '0'
122
136
  requirements: []
123
- rubyforge_project:
124
- rubygems_version: 2.7.6
137
+ rubygems_version: 3.1.2
125
138
  signing_key:
126
139
  specification_version: 4
127
140
  summary: Ruby library for running commands as elevated