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 CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NGM3NmFiYjNlN2IwZTI3YWNiNTJiYWViODg3MTlhYTNlZjZiMzlkNg==
5
- data.tar.gz: !binary |-
6
- ZmQ5NDI4Nzc0MzJiOGYxNzQ1NDZkODYwZTRhZmQ4OTQ1YjYxMmVhYQ==
2
+ SHA1:
3
+ metadata.gz: f89036d9e49a1aa022ad2a3a386c7c470c47bae3
4
+ data.tar.gz: 28a237b3cf0725a1deb0871f2a1b30a76f505025
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- NjU0MjZkMDFkNDAwMDQ3Y2I3NTJkZTVhMTQ5MTc3MzY1MTBhMzU0ZWZlYjAx
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
- whomai = Mixlib::ShellOut.new("whoami.exe", :user => "username", :domain => "DOMAIN", :password => "password")
42
+ whoami = Mixlib::ShellOut.new("whoami.exe", :user => "username", :domain => "DOMAIN", :password => "password")
43
43
  whoami.run_command
44
44
 
45
45
  ## Platform Support
@@ -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 nil unless group
204
- group.kind_of?(Integer) ? group : Etc.getgrnam(group.to_s).gid
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
@@ -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
- environment.each do |env_var,value|
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
- # Process group id of the child. Returned as a negative value so you can
151
- # put it directly in arguments to kill, wait, etc.
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
- @child_pgid
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
- # We cannot use setsid here since getpgid fails on AIX with EPERM
292
- # when parent and child have different sessions and the parent tries to get the process group,
293
- # hence we just create a new process group, and have the same session.
294
- Process.setpgrp
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
@@ -1,5 +1,5 @@
1
1
  module Mixlib
2
2
  class ShellOut
3
- VERSION = "2.0.1"
3
+ VERSION = "2.1.0"
4
4
  end
5
5
  end
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.1
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: 2014-12-19 00:00:00.000000000 Z
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: '2.0'
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: '2.0'
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.1
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