winrm-elevated 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,18 +1,17 @@
1
- # encoding: UTF-8
2
- #
3
- # Copyright 2015 Shawn Neal <sneal@sneal.net>
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License");
6
- # you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
-
17
- require 'winrm'
18
- require_relative 'winrm/shells/elevated'
1
+ #
2
+ # Copyright 2015 Shawn Neal <sneal@sneal.net>
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'winrm'
17
+ require_relative 'winrm/shells/elevated'
@@ -1,116 +1,116 @@
1
- $username = '<%= username %>'
2
- $password = '<%= password %>'
3
- $script_file = '<%= script_path %>'
4
-
5
- $interactive = '<%= interactive_logon %>'
6
- $pass_to_use = $password
7
- $logon_type = 1
8
- $logon_type_xml = "<LogonType>Password</LogonType>"
9
- if($pass_to_use.length -eq 0) {
10
- $pass_to_use = $null
11
- $logon_type = 5
12
- $logon_type_xml = ""
13
- }
14
- if($interactive -eq 'true') {
15
- $logon_type = 3
16
- $logon_type_xml = "<LogonType>InteractiveTokenOrPassword</LogonType>"
17
- }
18
-
19
- $task_name = "WinRM_Elevated_Shell"
20
- $out_file = [System.IO.Path]::GetTempFileName()
21
- $err_file = [System.IO.Path]::GetTempFileName()
22
-
23
- $task_xml = @'
24
- <?xml version="1.0" encoding="UTF-16"?>
25
- <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
26
- <Principals>
27
- <Principal id="Author">
28
- <UserId>{username}</UserId>
29
- {logon_type}
30
- <RunLevel>HighestAvailable</RunLevel>
31
- </Principal>
32
- </Principals>
33
- <Settings>
34
- <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
35
- <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
36
- <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
37
- <AllowHardTerminate>true</AllowHardTerminate>
38
- <StartWhenAvailable>false</StartWhenAvailable>
39
- <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
40
- <IdleSettings>
41
- <StopOnIdleEnd>false</StopOnIdleEnd>
42
- <RestartOnIdle>false</RestartOnIdle>
43
- </IdleSettings>
44
- <AllowStartOnDemand>true</AllowStartOnDemand>
45
- <Enabled>true</Enabled>
46
- <Hidden>false</Hidden>
47
- <RunOnlyIfIdle>false</RunOnlyIfIdle>
48
- <WakeToRun>false</WakeToRun>
49
- <ExecutionTimeLimit>PT24H</ExecutionTimeLimit>
50
- <Priority>4</Priority>
51
- </Settings>
52
- <Actions Context="Author">
53
- <Exec>
54
- <Command>cmd</Command>
55
- <Arguments>{arguments}</Arguments>
56
- </Exec>
57
- </Actions>
58
- </Task>
59
- '@
60
-
61
- $arguments = "/c powershell.exe -executionpolicy bypass -NoProfile -File $script_file &gt; $out_file 2&gt;$err_file"
62
-
63
- $task_xml = $task_xml.Replace("{arguments}", $arguments)
64
- $task_xml = $task_xml.Replace("{username}", $username)
65
- $task_xml = $task_xml.Replace("{logon_type}", $logon_type_xml)
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
73
-
74
- $registered_task = $folder.GetTask("\$task_name")
75
- $registered_task.Run($null) | Out-Null
76
-
77
- $timeout = 10
78
- $sec = 0
79
- while ( (!($registered_task.state -eq 4)) -and ($sec -lt $timeout) ) {
80
- Start-Sleep -s 1
81
- $sec++
82
- }
83
-
84
- function SlurpOutput($file, $cur_line, $out_type) {
85
- 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("$_")
92
- }
93
- }
94
- }
95
- return $cur_line
96
- }
97
-
98
- $err_cur_line = 0
99
- $out_cur_line = 0
100
- do {
101
- Start-Sleep -m 100
102
- $out_cur_line = SlurpOutput $out_file $out_cur_line 'out'
103
- $err_cur_line = SlurpOutput $err_file $err_cur_line 'err'
104
- } while (!($registered_task.state -eq 3))
105
-
106
- # We'll make a best effort to clean these files
107
- # But a reboot could possibly end the task while the process
108
- # still runs and locks the file. If we can't delete we don't want to fail
109
- try { Remove-Item $out_file -ErrorAction Stop } catch {}
110
- try { Remove-Item $err_file -ErrorAction Stop } catch {}
111
- try { Remove-Item $script_file -ErrorAction Stop } catch {}
112
-
113
- $exit_code = $registered_task.LastTaskResult
114
- [System.Runtime.Interopservices.Marshal]::ReleaseComObject($schedule) | Out-Null
115
-
116
- exit $exit_code
1
+ $username = '<%= username %>'
2
+ $password = '<%= password %>'
3
+ $script_file = '<%= script_path %>'
4
+
5
+ $interactive = '<%= interactive_logon %>'
6
+ $pass_to_use = $password
7
+ $logon_type = 1
8
+ $logon_type_xml = "<LogonType>Password</LogonType>"
9
+ if($pass_to_use.length -eq 0) {
10
+ $pass_to_use = $null
11
+ $logon_type = 5
12
+ $logon_type_xml = ""
13
+ }
14
+ if($interactive -eq 'true') {
15
+ $logon_type = 3
16
+ $logon_type_xml = "<LogonType>InteractiveTokenOrPassword</LogonType>"
17
+ }
18
+
19
+ $task_name = "WinRM_Elevated_Shell"
20
+ $out_file = [System.IO.Path]::GetTempFileName()
21
+ $err_file = [System.IO.Path]::GetTempFileName()
22
+
23
+ $task_xml = @'
24
+ <?xml version="1.0" encoding="UTF-16"?>
25
+ <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
26
+ <Principals>
27
+ <Principal id="Author">
28
+ <UserId>{username}</UserId>
29
+ {logon_type}
30
+ <RunLevel>HighestAvailable</RunLevel>
31
+ </Principal>
32
+ </Principals>
33
+ <Settings>
34
+ <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
35
+ <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
36
+ <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
37
+ <AllowHardTerminate>true</AllowHardTerminate>
38
+ <StartWhenAvailable>false</StartWhenAvailable>
39
+ <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
40
+ <IdleSettings>
41
+ <StopOnIdleEnd>false</StopOnIdleEnd>
42
+ <RestartOnIdle>false</RestartOnIdle>
43
+ </IdleSettings>
44
+ <AllowStartOnDemand>true</AllowStartOnDemand>
45
+ <Enabled>true</Enabled>
46
+ <Hidden>false</Hidden>
47
+ <RunOnlyIfIdle>false</RunOnlyIfIdle>
48
+ <WakeToRun>false</WakeToRun>
49
+ <ExecutionTimeLimit>PT24H</ExecutionTimeLimit>
50
+ <Priority>4</Priority>
51
+ </Settings>
52
+ <Actions Context="Author">
53
+ <Exec>
54
+ <Command>cmd</Command>
55
+ <Arguments>{arguments}</Arguments>
56
+ </Exec>
57
+ </Actions>
58
+ </Task>
59
+ '@
60
+
61
+ $arguments = "/c powershell.exe -executionpolicy bypass -NoProfile -File $script_file &gt; $out_file 2&gt;$err_file"
62
+
63
+ $task_xml = $task_xml.Replace("{arguments}", $arguments)
64
+ $task_xml = $task_xml.Replace("{username}", $username)
65
+ $task_xml = $task_xml.Replace("{logon_type}", $logon_type_xml)
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
73
+
74
+ $registered_task = $folder.GetTask("\$task_name")
75
+ $registered_task.Run($null) | Out-Null
76
+
77
+ $timeout = 10
78
+ $sec = 0
79
+ while ( (!($registered_task.state -eq 4)) -and ($sec -lt $timeout) ) {
80
+ Start-Sleep -s 1
81
+ $sec++
82
+ }
83
+
84
+ function SlurpOutput($file, $cur_line, $out_type) {
85
+ 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("$_")
92
+ }
93
+ }
94
+ }
95
+ return $cur_line
96
+ }
97
+
98
+ $err_cur_line = 0
99
+ $out_cur_line = 0
100
+ do {
101
+ Start-Sleep -m 100
102
+ $out_cur_line = SlurpOutput $out_file $out_cur_line 'out'
103
+ $err_cur_line = SlurpOutput $err_file $err_cur_line 'err'
104
+ } while (!($registered_task.state -eq 3))
105
+
106
+ # We'll make a best effort to clean these files
107
+ # But a reboot could possibly end the task while the process
108
+ # still runs and locks the file. If we can't delete we don't want to fail
109
+ try { Remove-Item $out_file -ErrorAction Stop } catch {}
110
+ try { Remove-Item $err_file -ErrorAction Stop } catch {}
111
+ try { Remove-Item $script_file -ErrorAction Stop } catch {}
112
+
113
+ $exit_code = $registered_task.LastTaskResult
114
+ [System.Runtime.Interopservices.Marshal]::ReleaseComObject($schedule) | Out-Null
115
+
116
+ exit $exit_code
@@ -1,104 +1,103 @@
1
- # encoding: UTF-8
2
- #
3
- # Copyright 2015 Shawn Neal <sneal@sneal.net>
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License");
6
- # you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
-
17
- require 'erubis'
18
- require 'winrm'
19
- require 'winrm-fs'
20
- require 'securerandom'
21
-
22
- module WinRM
23
- module Shells
24
- # Runs PowerShell commands elevated via a scheduled task
25
- class Elevated
26
- # Create a new elevated shell
27
- # @param connection_opts [ConnectionOpts] The WinRM connection options
28
- # @param transport [HttpTransport] The WinRM SOAP transport
29
- # @param logger [Logger] The logger to log diagnostic messages to
30
- def initialize(connection_opts, transport, logger)
31
- @logger = logger
32
- @username = connection_opts[:user]
33
- @password = connection_opts[:password]
34
- @interactive_logon = false
35
- @shell = Powershell.new(connection_opts, transport, logger)
36
- @winrm_file_transporter = WinRM::FS::Core::FileTransporter.new(@shell)
37
- end
38
-
39
- # @return [String] The admin user name to execute the scheduled task as
40
- attr_accessor :username
41
-
42
- # @return [String] The admin user password
43
- attr_accessor :password
44
-
45
- # @return [Bool] Using an interactive logon
46
- attr_accessor :interactive_logon
47
-
48
- # Run a command or PowerShell script elevated without any of the
49
- # restrictions that WinRM puts in place.
50
- #
51
- # @param [String] The command or PS script to wrap in a scheduled task
52
- #
53
- # @return [WinRM::Output] :stdout and :stderr
54
- def run(command, &block)
55
- # if an IO object is passed read it, otherwise assume the contents of the file were passed
56
- script_text = command.respond_to?(:read) ? command.read : command
57
-
58
- script_path = upload_elevated_shell_script(script_text)
59
- wrapped_script = wrap_in_scheduled_task(script_path, username, password)
60
- @shell.run(wrapped_script, &block)
61
- end
62
-
63
- # Closes the shell if one is open
64
- def close
65
- @shell.close
66
- end
67
-
68
- private
69
-
70
- def upload_elevated_shell_script(script_text)
71
- elevated_shell_path = 'c:/windows/temp/winrm-elevated-shell-' + SecureRandom.uuid + '.ps1'
72
- with_temp_file(script_text) do |temp_file|
73
- @winrm_file_transporter.upload(temp_file, elevated_shell_path)
74
- end
75
- elevated_shell_path
76
- end
77
-
78
- def with_temp_file(script_text)
79
- file = Tempfile.new(['winrm-elevated-shell', 'ps1'])
80
- file.write(script_text)
81
- file.write("\r\n$Host.SetShouldExit($LASTEXITCODE)")
82
- file.fsync
83
- file.close
84
- yield file.path
85
- ensure
86
- file.close
87
- file.unlink
88
- end
89
-
90
- def elevated_shell_script_content
91
- IO.read(File.expand_path('../../../winrm-elevated/scripts/elevated_shell.ps1', __FILE__))
92
- end
93
-
94
- def wrap_in_scheduled_task(script_path, username, password)
95
- Erubis::Eruby.new(elevated_shell_script_content).result(
96
- username: username,
97
- password: password,
98
- script_path: script_path,
99
- interactive_logon: interactive_logon
100
- )
101
- end
102
- end
103
- end
104
- end
1
+ #
2
+ # Copyright 2015 Shawn Neal <sneal@sneal.net>
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'erubis'
17
+ require 'winrm'
18
+ require 'winrm-fs'
19
+ require 'securerandom'
20
+
21
+ module WinRM
22
+ module Shells
23
+ # Runs PowerShell commands elevated via a scheduled task
24
+ class Elevated
25
+ # Create a new elevated shell
26
+ # @param connection_opts [ConnectionOpts] The WinRM connection options
27
+ # @param transport [HttpTransport] The WinRM SOAP transport
28
+ # @param logger [Logger] The logger to log diagnostic messages to
29
+ def initialize(connection_opts, transport, logger)
30
+ @logger = logger
31
+ @username = connection_opts[:user]
32
+ @password = connection_opts[:password]
33
+ @interactive_logon = false
34
+ @shell = Powershell.new(connection_opts, transport, logger)
35
+ @winrm_file_transporter = WinRM::FS::Core::FileTransporter.new(@shell)
36
+ end
37
+
38
+ # @return [String] The admin user name to execute the scheduled task as
39
+ attr_accessor :username
40
+
41
+ # @return [String] The admin user password
42
+ attr_accessor :password
43
+
44
+ # @return [Bool] Using an interactive logon
45
+ attr_accessor :interactive_logon
46
+
47
+ # Run a command or PowerShell script elevated without any of the
48
+ # restrictions that WinRM puts in place.
49
+ #
50
+ # @param [String] The command or PS script to wrap in a scheduled task
51
+ #
52
+ # @return [WinRM::Output] :stdout and :stderr
53
+ def run(command, &block)
54
+ # if an IO object is passed read it, otherwise assume the contents of the file were passed
55
+ script_text = command.respond_to?(:read) ? command.read : command
56
+
57
+ script_path = upload_elevated_shell_script(script_text)
58
+ wrapped_script = wrap_in_scheduled_task(script_path, username, password)
59
+ @shell.run(wrapped_script, &block)
60
+ end
61
+
62
+ # Closes the shell if one is open
63
+ def close
64
+ @shell.close
65
+ end
66
+
67
+ private
68
+
69
+ def upload_elevated_shell_script(script_text)
70
+ 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
74
+ elevated_shell_path
75
+ end
76
+
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
+ def elevated_shell_script_content
90
+ IO.read(File.expand_path('../../winrm-elevated/scripts/elevated_shell.ps1', __dir__))
91
+ end
92
+
93
+ def wrap_in_scheduled_task(script_path, username, password)
94
+ Erubis::Eruby.new(elevated_shell_script_content).result(
95
+ username: username,
96
+ password: password,
97
+ script_path: script_path,
98
+ interactive_logon: interactive_logon
99
+ )
100
+ end
101
+ end
102
+ end
103
+ end