mixlib-shellout 2.0.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/README.md +1 -1
- data/lib/mixlib/shellout.rb +18 -3
- data/lib/mixlib/shellout/unix.rb +58 -25
- data/lib/mixlib/shellout/version.rb +1 -1
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
ZmQ5NDI4Nzc0MzJiOGYxNzQ1NDZkODYwZTRhZmQ4OTQ1YjYxMmVhYQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f89036d9e49a1aa022ad2a3a386c7c470c47bae3
|
4
|
+
data.tar.gz: 28a237b3cf0725a1deb0871f2a1b30a76f505025
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
NjBlMTU2ZmRiODAyNjI4ODlkOWEzYmFiNzJjNzc3YTg5NWQ4MzVmZDViM2Iw
|
11
|
-
YWQyMWIyNTcxYjUxNjVjNTk4YjdiNGJkYjc2NmE4YzhhYjlkZjI=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MmE4ZjAxOGU0ZGM3OTY3M2EyZmExMjJkODI1ZDE0YmQwZDU4ZGY0YzQyYThh
|
14
|
-
MzI1NDdkMTc3MGFkNGQwZDA5NmJjMzg2NmFhNWQzOWExMDczZTFkZWQ5NzVh
|
15
|
-
YWVlNjRlNTEyN2VlMDU1YTY3M2I5NDFlZDI3NTk2OTU5ZTk1YWQ=
|
6
|
+
metadata.gz: 7c06cca58cd3c1192c1d591e95c4ddd79961de7eca1a4f255ef70443c4c4dd323f8a07db4f0681d58f759fc3048ffa03081956d1277cdf8b356be86a6a9d7358
|
7
|
+
data.tar.gz: f9964010b07fc39958ff65ff37b4906c6f1867ab7262e4dbc2c4df32500de257536c50007e02466869f495ae260c284eb78a9d7d9b6cf90b0affdabc1943c044
|
data/README.md
CHANGED
@@ -39,7 +39,7 @@ Invoke crontab to edit user cron:
|
|
39
39
|
## Windows Impersonation Example
|
40
40
|
Invoke "whoami.exe" to demonstrate running a command as another user:
|
41
41
|
|
42
|
-
|
42
|
+
whoami = Mixlib::ShellOut.new("whoami.exe", :user => "username", :domain => "DOMAIN", :password => "password")
|
43
43
|
whoami.run_command
|
44
44
|
|
45
45
|
## Platform Support
|
data/lib/mixlib/shellout.rb
CHANGED
@@ -40,8 +40,13 @@ module Mixlib
|
|
40
40
|
attr_accessor :user
|
41
41
|
attr_accessor :domain
|
42
42
|
attr_accessor :password
|
43
|
+
# TODO remove
|
43
44
|
attr_accessor :with_logon
|
44
45
|
|
46
|
+
# Whether to simulate logon as the user. Normally set via options passed to new
|
47
|
+
# Always enabled on windows
|
48
|
+
attr_accessor :login
|
49
|
+
|
45
50
|
# Group the command will run as. Normally set via options passed to new
|
46
51
|
attr_accessor :group
|
47
52
|
|
@@ -141,6 +146,8 @@ module Mixlib
|
|
141
146
|
# child process. Generally this is used to copy data from the child to
|
142
147
|
# the parent's stdout so that users may observe the progress of
|
143
148
|
# long-running commands.
|
149
|
+
# * +login+: Whether to simulate a login (set secondary groups, primary group, environment
|
150
|
+
# variables etc) as done by the OS in an actual login
|
144
151
|
# === Examples:
|
145
152
|
# Invoke find(1) to search for .rb files:
|
146
153
|
# find = Mixlib::ShellOut.new("find . -name '*.rb'")
|
@@ -164,6 +171,7 @@ module Mixlib
|
|
164
171
|
@cwd = nil
|
165
172
|
@valid_exit_codes = [0]
|
166
173
|
@terminate_reason = nil
|
174
|
+
@timeout = nil
|
167
175
|
|
168
176
|
if command_args.last.is_a?(Hash)
|
169
177
|
parse_options(command_args.pop)
|
@@ -192,6 +200,7 @@ module Mixlib
|
|
192
200
|
|
193
201
|
# The uid that the subprocess will switch to. If the user attribute was
|
194
202
|
# given as a username, it is converted to a uid by Etc.getpwnam
|
203
|
+
# TODO migrate to shellout/unix.rb
|
195
204
|
def uid
|
196
205
|
return nil unless user
|
197
206
|
user.kind_of?(Integer) ? user : Etc.getpwnam(user.to_s).uid
|
@@ -199,9 +208,11 @@ module Mixlib
|
|
199
208
|
|
200
209
|
# The gid that the subprocess will switch to. If the group attribute is
|
201
210
|
# given as a group name, it is converted to a gid by Etc.getgrnam
|
211
|
+
# TODO migrate to shellout/unix.rb
|
202
212
|
def gid
|
203
|
-
return
|
204
|
-
|
213
|
+
return group.kind_of?(Integer) ? group : Etc.getgrnam(group.to_s).gid if group
|
214
|
+
return Etc.getpwuid(uid).gid if using_login?
|
215
|
+
return nil
|
205
216
|
end
|
206
217
|
|
207
218
|
def timeout
|
@@ -322,7 +333,8 @@ module Mixlib
|
|
322
333
|
self.log_tag = setting
|
323
334
|
when 'environment', 'env'
|
324
335
|
self.environment = setting || {}
|
325
|
-
|
336
|
+
when 'login'
|
337
|
+
self.login = setting
|
326
338
|
else
|
327
339
|
raise InvalidCommandOption, "option '#{option.inspect}' is not a valid option for #{self.class.name}"
|
328
340
|
end
|
@@ -332,6 +344,9 @@ module Mixlib
|
|
332
344
|
end
|
333
345
|
|
334
346
|
def validate_options(opts)
|
347
|
+
if login && !user
|
348
|
+
raise InvalidCommandOption, "cannot set login without specifying a user"
|
349
|
+
end
|
335
350
|
super
|
336
351
|
end
|
337
352
|
end
|
data/lib/mixlib/shellout/unix.rb
CHANGED
@@ -30,6 +30,47 @@ module Mixlib
|
|
30
30
|
# No options to validate, raise exceptions here if needed
|
31
31
|
end
|
32
32
|
|
33
|
+
# Whether we're simulating a login shell
|
34
|
+
def using_login?
|
35
|
+
return login && user
|
36
|
+
end
|
37
|
+
|
38
|
+
# Helper method for sgids
|
39
|
+
def all_seconderies
|
40
|
+
ret = []
|
41
|
+
Etc.endgrent
|
42
|
+
while ( g = Etc.getgrent ) do
|
43
|
+
ret << g
|
44
|
+
end
|
45
|
+
Etc.endgrent
|
46
|
+
return ret
|
47
|
+
end
|
48
|
+
|
49
|
+
# The secondary groups that the subprocess will switch to.
|
50
|
+
# Currently valid only if login is used, and is set
|
51
|
+
# to the user's secondary groups
|
52
|
+
def sgids
|
53
|
+
return nil unless using_login?
|
54
|
+
user_name = Etc.getpwuid(uid).name
|
55
|
+
all_seconderies.select{|g| g.mem.include?(user_name)}.map{|g|g.gid}
|
56
|
+
end
|
57
|
+
|
58
|
+
# The environment variables that are deduced from simulating logon
|
59
|
+
# Only valid if login is used
|
60
|
+
def logon_environment
|
61
|
+
return {} unless using_login?
|
62
|
+
entry = Etc.getpwuid(uid)
|
63
|
+
# According to `man su`, the set fields are:
|
64
|
+
# $HOME, $SHELL, $USER, $LOGNAME, $PATH, and $IFS
|
65
|
+
# Values are copied from "shadow" package in Ubuntu 14.10
|
66
|
+
{'HOME'=>entry.dir, 'SHELL'=>entry.shell, 'USER'=>entry.name, 'LOGNAME'=>entry.name, 'PATH'=>'/sbin:/bin:/usr/sbin:/usr/bin', 'IFS'=>"\t\n"}
|
67
|
+
end
|
68
|
+
|
69
|
+
# Merges the two environments for the process
|
70
|
+
def process_environment
|
71
|
+
logon_environment.merge(self.environment)
|
72
|
+
end
|
73
|
+
|
33
74
|
# Run the command, writing the command's standard out and standard error
|
34
75
|
# to +stdout+ and +stderr+, and saving its exit status object to +status+
|
35
76
|
# === Returns
|
@@ -63,8 +104,8 @@ module Mixlib
|
|
63
104
|
# CHEF-3390: Marshall.load on Ruby < 1.8.7p369 also has a GC bug related
|
64
105
|
# to Marshall.load, so try disabling GC first.
|
65
106
|
propagate_pre_exec_failure
|
66
|
-
get_child_pgid
|
67
107
|
|
108
|
+
@status = nil
|
68
109
|
@result = nil
|
69
110
|
@execution_time = 0
|
70
111
|
|
@@ -107,18 +148,6 @@ module Mixlib
|
|
107
148
|
|
108
149
|
private
|
109
150
|
|
110
|
-
def get_child_pgid
|
111
|
-
# The behavior of Process.getpgid (see also getpgid(2) ) when the
|
112
|
-
# argument is the pid of a zombie isn't well specified. On Linux it
|
113
|
-
# works, on OS X it returns ESRCH (which ruby turns into Errno::ESRCH).
|
114
|
-
#
|
115
|
-
# If the child dies very quickly, @child_pid may be a zombie, so handle
|
116
|
-
# ESRCH here.
|
117
|
-
@child_pgid = -Process.getpgid(@child_pid)
|
118
|
-
rescue Errno::ESRCH, Errno::EPERM
|
119
|
-
@child_pgid = nil
|
120
|
-
end
|
121
|
-
|
122
151
|
def set_user
|
123
152
|
if user
|
124
153
|
Process.uid = uid
|
@@ -133,8 +162,15 @@ module Mixlib
|
|
133
162
|
end
|
134
163
|
end
|
135
164
|
|
165
|
+
def set_secondarygroups
|
166
|
+
if sgids
|
167
|
+
Process.groups = sgids
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
136
171
|
def set_environment
|
137
|
-
|
172
|
+
# user-set variables should override the login ones
|
173
|
+
process_environment.each do |env_var,value|
|
138
174
|
ENV[env_var] = value
|
139
175
|
end
|
140
176
|
end
|
@@ -147,14 +183,10 @@ module Mixlib
|
|
147
183
|
Dir.chdir(cwd) if cwd
|
148
184
|
end
|
149
185
|
|
150
|
-
#
|
151
|
-
#
|
152
|
-
#
|
153
|
-
# This may be nil if the child dies before the parent can query the
|
154
|
-
# system for its pgid (on some systems it is an error to get the pgid of
|
155
|
-
# a zombie).
|
186
|
+
# Since we call setsid the child_pgid will be the child_pid, set to negative here
|
187
|
+
# so it can be directly used in arguments to kill, wait, etc.
|
156
188
|
def child_pgid
|
157
|
-
|
189
|
+
-@child_pid
|
158
190
|
end
|
159
191
|
|
160
192
|
def initialize_ipc
|
@@ -288,13 +320,14 @@ module Mixlib
|
|
288
320
|
# support the "ONESHOT" optimization (where sh -c does exec without
|
289
321
|
# forking). To support cleaning up all the children, we need to
|
290
322
|
# ensure they're in a unique process group.
|
291
|
-
#
|
292
|
-
#
|
293
|
-
#
|
294
|
-
Process.
|
323
|
+
#
|
324
|
+
# We use setsid here to abandon our controlling tty and get a new session
|
325
|
+
# and process group that are set to the pid of the child process.
|
326
|
+
Process.setsid
|
295
327
|
|
296
328
|
configure_subprocess_file_descriptors
|
297
329
|
|
330
|
+
set_secondarygroups
|
298
331
|
set_group
|
299
332
|
set_user
|
300
333
|
set_environment
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mixlib-shellout
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Opscode
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-05-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '3.0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '3.0'
|
27
27
|
description: Run external commands on Unix or Windows
|
28
28
|
email: info@opscode.com
|
29
29
|
executables: []
|
@@ -49,17 +49,17 @@ require_paths:
|
|
49
49
|
- lib
|
50
50
|
required_ruby_version: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 1.9.3
|
55
55
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
56
|
requirements:
|
57
|
-
- -
|
57
|
+
- - ">="
|
58
58
|
- !ruby/object:Gem::Version
|
59
59
|
version: '0'
|
60
60
|
requirements: []
|
61
61
|
rubyforge_project:
|
62
|
-
rubygems_version: 2.4.
|
62
|
+
rubygems_version: 2.4.6
|
63
63
|
signing_key:
|
64
64
|
specification_version: 4
|
65
65
|
summary: Run external commands on Unix or Windows
|