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 +4 -4
- data/lib/winrm-elevated.rb +1 -1
- data/lib/winrm-elevated/scripts/elevated_shell.ps1 +55 -21
- data/lib/winrm/shells/elevated.rb +21 -21
- metadata +18 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ee0adbdb22c257558248a863ab41505ef63bbe664150084be3cd57ecc56eef3e
|
|
4
|
+
data.tar.gz: d3442d4883f6617827977d6c2538f8d4961a1bf45de3e45be4c249e34ec548c3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 439dfd36cc9777886088dccb8172885844f319f3e808fb951b2eac31e115367e500f97b9d6fc2d0006588a7c1a8bedbb034d8af1678bc6d39d10647c6db2a958
|
|
7
|
+
data.tar.gz: 63935500fcb295b1359c2222cb1860788fbb2f7859c2f303c8928b61b478197c72e4fa2163070873e333e45d822a7164ea365947cdb5b7c3a6ca117ff20bdbc5
|
data/lib/winrm-elevated.rb
CHANGED
|
@@ -16,7 +16,7 @@ if($interactive -eq 'true') {
|
|
|
16
16
|
$logon_type_xml = "<LogonType>InteractiveTokenOrPassword</LogonType>"
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
$task_name = "
|
|
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
|
-
|
|
68
|
-
$schedule.
|
|
69
|
-
$
|
|
70
|
-
$task
|
|
71
|
-
$
|
|
72
|
-
$folder
|
|
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
|
-
|
|
81
|
-
|
|
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
|
-
|
|
87
|
-
$
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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 '
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
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.
|
|
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:
|
|
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.
|
|
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
|
-
|
|
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
|