diff options
author | Nick Lewis <nick@puppetlabs.com> | 2011-08-17 14:44:03 -0700 |
---|---|---|
committer | Nick Lewis <nick@puppetlabs.com> | 2011-08-17 14:44:03 -0700 |
commit | cf95530964a067374f2ff8be0602342e47a55cc5 (patch) | |
tree | eeec7ada4ec86ededf527fe2108f839251e41869 | |
parent | 54fb365120463e240328cd6fe507423e6d022110 (diff) | |
parent | 99678f26369f7ac57a4125b6b391f2db832bbb4b (diff) | |
download | puppet-cf95530964a067374f2ff8be0602342e47a55cc5.tar.gz puppet-cf95530964a067374f2ff8be0602342e47a55cc5.tar.xz puppet-cf95530964a067374f2ff8be0602342e47a55cc5.zip |
Merge branch '2.7.x'
-rw-r--r-- | acceptance/tests/resource/file/ticket_8740_should_not_enumerate_root_directory.rb | 32 | ||||
-rw-r--r-- | lib/puppet/application/resource.rb | 3 | ||||
-rw-r--r-- | lib/puppet/type/augeas.rb | 32 | ||||
-rwxr-xr-x | lib/puppet/type/cron.rb | 25 | ||||
-rw-r--r-- | lib/puppet/type/file.rb | 4 | ||||
-rw-r--r-- | lib/puppet/util.rb | 56 | ||||
-rw-r--r-- | lib/puppet/util/suidmanager.rb | 62 | ||||
-rwxr-xr-x | spec/unit/application/resource_spec.rb | 25 | ||||
-rwxr-xr-x | spec/unit/configurer_spec.rb | 5 | ||||
-rwxr-xr-x | spec/unit/face/node_spec.rb | 4 | ||||
-rwxr-xr-x | spec/unit/type/file_spec.rb | 6 | ||||
-rwxr-xr-x | spec/unit/util/suidmanager_spec.rb | 210 | ||||
-rwxr-xr-x | test/puppet/tc_suidmanager.rb | 120 |
13 files changed, 383 insertions, 201 deletions
diff --git a/acceptance/tests/resource/file/ticket_8740_should_not_enumerate_root_directory.rb b/acceptance/tests/resource/file/ticket_8740_should_not_enumerate_root_directory.rb new file mode 100644 index 000000000..5763a3c98 --- /dev/null +++ b/acceptance/tests/resource/file/ticket_8740_should_not_enumerate_root_directory.rb @@ -0,0 +1,32 @@ +test_name "#8740: should not enumerate root directory" + +target = "/test-socket-#{$$}" + +step "clean up the system before we begin" +on(agents, "rm -f #{target}") + +step "create UNIX domain socket" +on(agents, %Q{ruby -e "require 'socket'; UNIXServer::new('#{target}').close"}) + +step "query for all files, which should return nothing" +on(agents, puppet_resource('file'), :acceptable_exit_codes => [1]) do + assert_match(%r{Listing all file instances is not supported. Please specify a file or directory, e.g. puppet resource file /etc}, stderr) +end + +["/", "/etc"].each do |file| + step "query '#{file}' directory, which should return single entry" + on(agents, puppet_resource('file', file)) do + files = stdout.scan(/^file \{ '([^']+)'/).flatten + + assert_equal(1, files.size, "puppet returned multiple files: #{files.join(', ')}") + assert_match(file, files[0], "puppet did not return file") + end +end + +step "query file that does not exist, which should report the file is absent" +on(agents, puppet_resource('file', '/this/does/notexist')) do + assert_match(/ensure\s+=>\s+'absent'/, stdout) +end + +step "remove UNIX domain socket" +on(agents, "rm -f #{target}") diff --git a/lib/puppet/application/resource.rb b/lib/puppet/application/resource.rb index 6ef87d68f..76d0fada8 100644 --- a/lib/puppet/application/resource.rb +++ b/lib/puppet/application/resource.rb @@ -183,6 +183,9 @@ Copyright (c) 2011 Puppet Labs, LLC Licensed under the Apache 2.0 License [ Puppet::Resource.indirection.save(Puppet::Resource.new( type, name, :parameters => params ), key) ] end else + if type == "file" + raise "Listing all file instances is not supported. Please specify a file or directory, e.g. puppet resource file /etc" + end Puppet::Resource.indirection.search( key, {} ) end.map(&format).join("\n") diff --git a/lib/puppet/type/augeas.rb b/lib/puppet/type/augeas.rb index f4d3c43e1..f02cfe6e2 100644 --- a/lib/puppet/type/augeas.rb +++ b/lib/puppet/type/augeas.rb @@ -20,7 +20,8 @@ Puppet::Type.newtype(:augeas) do feature :need_to_run?, "If the command should run" feature :execute_changes, "Actually make the changes" - @doc = "Apply the changes (single or array of changes) to the filesystem + @doc = <<-EOT + Apply the changes (single or array of changes) to the filesystem via the augeas tool. Requires: @@ -30,24 +31,24 @@ Puppet::Type.newtype(:augeas) do Sample usage with a string: - augeas{\"test1\" : - context => \"/files/etc/sysconfig/firstboot\", - changes => \"set RUN_FIRSTBOOT YES\", - onlyif => \"match other_value size > 0\", + augeas{"test1" : + context => "/files/etc/sysconfig/firstboot", + changes => "set RUN_FIRSTBOOT YES", + onlyif => "match other_value size > 0", } Sample usage with an array and custom lenses: - augeas{\"jboss_conf\": - context => \"/files\", + augeas{"jboss_conf": + context => "/files", changes => [ - \"set /etc/jbossas/jbossas.conf/JBOSS_IP $ipaddress\", - \"set /etc/jbossas/jbossas.conf/JAVA_HOME /usr\" + "set etc/jbossas/jbossas.conf/JBOSS_IP $ipaddress", + "set etc/jbossas/jbossas.conf/JAVA_HOME /usr", ], - load_path => \"$/usr/share/jbossas/lenses\", + load_path => "$/usr/share/jbossas/lenses", } - " + EOT newparam (:name) do desc "The name of this task. Used for uniqueness" @@ -95,13 +96,18 @@ Puppet::Type.newtype(:augeas) do Commands supported are: set [PATH] [VALUE] Sets the value VALUE at loction PATH + setm [PATH] [SUB] [VALUE] Sets multiple nodes matching SUB relative to PATH, to VALUE rm [PATH] Removes the node at location PATH remove [PATH] Synonym for rm - clear [PATH] Keeps the node at PATH, but removes the value. + clear [PATH] Sets the node at PATH to NULL, creating it if needed ins [LABEL] [WHERE] [PATH] Inserts an empty node LABEL either [WHERE={before|after}] PATH. insert [LABEL] [WHERE] [PATH] Synonym for ins + mv [PATH] [PATH] Moves a node at PATH to the new location PATH + move [PATH] [PATH] Synonym for mv + defvar [NAME] [PATH] Sets Augeas variable $NAME to PATH + defnode [NAME] [PATH] [VALUE] Sets Augeas variable $NAME to PATH, creating it with VALUE if needed - If the parameter 'context' is set that value is prepended to PATH" + If the parameter 'context' is set that value is prepended to a relative PATH" end diff --git a/lib/puppet/type/cron.rb b/lib/puppet/type/cron.rb index 5083ca556..6e9caa75b 100755 --- a/lib/puppet/type/cron.rb +++ b/lib/puppet/type/cron.rb @@ -3,11 +3,12 @@ require 'facter' require 'puppet/util/filetype' Puppet::Type.newtype(:cron) do - @doc = "Installs and manages cron jobs. All fields except the command - and the user are optional, although specifying no periodic - fields would result in the command being executed every - minute. While the name of the cron job is not part of the actual - job, it is used by Puppet to store and retrieve it. + @doc = <<-EOT + Installs and manages cron jobs. Every cron resource requires a command + and user attribute, as well as at least one periodic attribute (hour, + minute, month, monthday, weekday, or special). While the name of the cron + job is not part of the actual job, it is used by Puppet to store and + retrieve it. If you specify a cron job that matches an existing job in every way except name, then the jobs will be considered equivalent and the @@ -18,30 +19,30 @@ Puppet::Type.newtype(:cron) do Example: cron { logrotate: - command => \"/usr/sbin/logrotate\", + command => "/usr/sbin/logrotate", user => root, hour => 2, minute => 0 } - Note that all cron values can be specified as an array of values: + Note that all periodic attributes can be specified as an array of values: cron { logrotate: - command => \"/usr/sbin/logrotate\", + command => "/usr/sbin/logrotate", user => root, hour => [2, 4] } - Or using ranges, or the step syntax `*/2` (although there's no guarantee that - your `cron` daemon supports it): + ...or using ranges or the step syntax `*/2` (although there's no guarantee + that your `cron` daemon supports these): cron { logrotate: - command => \"/usr/sbin/logrotate\", + command => "/usr/sbin/logrotate", user => root, hour => ['2-4'], minute => '*/10' } - " + EOT ensurable # A base class for all of the Cron parameters, since they all have diff --git a/lib/puppet/type/file.rb b/lib/puppet/type/file.rb index 07409a108..fc4926581 100644 --- a/lib/puppet/type/file.rb +++ b/lib/puppet/type/file.rb @@ -330,8 +330,8 @@ Puppet::Type.newtype(:file) do super(path.gsub(/\/+/, '/').sub(/\/$/, '')) end - def self.instances(base = '/') - return self.new(:name => base, :recurse => true, :recurselimit => 1, :audit => :all).recurse_local.values + def self.instances + return [] end # Determine the user to write files as. diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb index ff09221a2..ecedb25a6 100644 --- a/lib/puppet/util.rb +++ b/lib/puppet/util.rb @@ -47,35 +47,24 @@ module Util # Change the process to a different user def self.chuser if group = Puppet[:group] - group = self.gid(group) - raise Puppet::Error, "No such group #{Puppet[:group]}" unless group - unless Puppet::Util::SUIDManager.gid == group - begin - Puppet::Util::SUIDManager.egid = group - Puppet::Util::SUIDManager.gid = group - rescue => detail - Puppet.warning "could not change to group #{group.inspect}: #{detail}" - $stderr.puts "could not change to group #{group.inspect}" - - # Don't exit on failed group changes, since it's - # not fatal - #exit(74) - end + begin + Puppet::Util::SUIDManager.change_group(group, true) + rescue => detail + Puppet.warning "could not change to group #{group.inspect}: #{detail}" + $stderr.puts "could not change to group #{group.inspect}" + + # Don't exit on failed group changes, since it's + # not fatal + #exit(74) end end if user = Puppet[:user] - user = self.uid(user) - raise Puppet::Error, "No such user #{Puppet[:user]}" unless user - unless Puppet::Util::SUIDManager.uid == user - begin - Puppet::Util::SUIDManager.initgroups(user) - Puppet::Util::SUIDManager.uid = user - Puppet::Util::SUIDManager.euid = user - rescue => detail - $stderr.puts "Could not change to user #{user}: #{detail}" - exit(74) - end + begin + Puppet::Util::SUIDManager.change_user(user, true) + rescue => detail + $stderr.puts "Could not change to user #{user}: #{detail}" + exit(74) end end end @@ -90,18 +79,14 @@ module Util if useself Puppet::Util::Log.create( - :level => level, :source => self, - :message => args ) else Puppet::Util::Log.create( - :level => level, - :message => args ) end @@ -262,9 +247,6 @@ module Util Puppet.debug "Executing '#{str}'" end - arguments[:uid] = Puppet::Util::SUIDManager.convert_xid(:uid, arguments[:uid]) if arguments[:uid] - arguments[:gid] = Puppet::Util::SUIDManager.convert_xid(:gid, arguments[:gid]) if arguments[:gid] - if execution_stub = Puppet::Util::ExecutionStub.current_value return execution_stub.call(command, arguments) end @@ -306,14 +288,8 @@ module Util $stderr.reopen(error_file) 3.upto(256){|fd| IO::new(fd).close rescue nil} - if arguments[:gid] - Process.egid = arguments[:gid] - Process.gid = arguments[:gid] unless @@os == "Darwin" - end - if arguments[:uid] - Process.euid = arguments[:uid] - Process.uid = arguments[:uid] unless @@os == "Darwin" - end + Puppet::Util::SUIDManager.change_group(arguments[:gid], true) if arguments[:gid] + Puppet::Util::SUIDManager.change_user(arguments[:uid], true) if arguments[:uid] ENV['LANG'] = ENV['LC_ALL'] = ENV['LC_MESSAGES'] = ENV['LANGUAGE'] = 'C' if command.is_a?(Array) Kernel.exec(*command) diff --git a/lib/puppet/util/suidmanager.rb b/lib/puppet/util/suidmanager.rb index 6633de002..697bce111 100644 --- a/lib/puppet/util/suidmanager.rb +++ b/lib/puppet/util/suidmanager.rb @@ -36,12 +36,6 @@ module Puppet::Util::SUIDManager end module_function :groups= - if Facter['kernel'].value == 'Darwin' - # Cannot change real UID on Darwin so we set euid - alias :uid :euid - alias :gid :egid - end - def self.root? Process.uid == 0 end @@ -50,23 +44,63 @@ module Puppet::Util::SUIDManager def asuser(new_uid=nil, new_gid=nil) return yield if Puppet.features.microsoft_windows? or !root? - # We set both because some programs like to drop privs, i.e. bash. - old_uid, old_gid = self.uid, self.gid old_euid, old_egid = self.euid, self.egid - old_groups = self.groups begin - self.egid = convert_xid :gid, new_gid if new_gid - self.initgroups(convert_xid(:uid, new_uid)) if new_uid - self.euid = convert_xid :uid, new_uid if new_uid + change_group(new_gid) if new_gid + change_user(new_uid) if new_uid yield ensure - self.euid, self.egid = old_euid, old_egid - self.groups = old_groups + change_group(old_egid) + change_user(old_euid) end end module_function :asuser + def change_group(group, permanently=false) + gid = convert_xid(:gid, group) + raise Puppet::Error, "No such group #{group}" unless gid + + if permanently + begin + Process::GID.change_privilege(gid) + rescue NotImplementedError + Process.egid = gid + Process.gid = gid + end + else + Process.egid = gid + end + end + module_function :change_group + + def change_user(user, permanently=false) + uid = convert_xid(:uid, user) + raise Puppet::Error, "No such user #{user}" unless uid + + if permanently + begin + Process::UID.change_privilege(uid) + rescue NotImplementedError + # If changing uid, we must be root. So initgroups first here. + initgroups(uid) + Process.euid = uid + Process.uid = uid + end + else + # If we're already root, initgroups before changing euid. If we're not, + # change euid (to root) first. + if Process.euid == 0 + initgroups(uid) + Process.euid = uid + else + Process.euid = uid + initgroups(uid) + end + end + end + module_function :change_user + # Make sure the passed argument is a number. def convert_xid(type, id) map = {:gid => :group, :uid => :user} diff --git a/spec/unit/application/resource_spec.rb b/spec/unit/application/resource_spec.rb index a6564cae5..01cd17e00 100755 --- a/spec/unit/application/resource_spec.rb +++ b/spec/unit/application/resource_spec.rb @@ -221,4 +221,29 @@ describe Puppet::Application::Resource do end end + + describe "when handling file type" do + before :each do + Facter.stubs(:loadfacts) + @resource.preinit + end + + it "should raise an exception if no file specified" do + @resource.command_line.stubs(:args).returns(['file']) + + lambda { @resource.main }.should raise_error(RuntimeError, /Listing all file instances is not supported/) + end + + it "should output a file resource when given a file path" do + res = Puppet::Type.type(:file).new(:path => "/etc").to_resource + Puppet::Resource.indirection.expects(:find).returns(res) + + @resource.command_line.stubs(:args).returns(['file', '/etc']) + @resource.expects(:puts).with do |args| + args.should =~ /file \{ '\/etc'/m + end + + @resource.main + end + end end diff --git a/spec/unit/configurer_spec.rb b/spec/unit/configurer_spec.rb index 020d1850f..588f1659b 100755 --- a/spec/unit/configurer_spec.rb +++ b/spec/unit/configurer_spec.rb @@ -93,6 +93,11 @@ describe Puppet::Configurer do Puppet::Util::Log.stubs(:close_all) end + after :all do + Puppet::Node::Facts.indirection.reset_terminus_class + Puppet::Resource::Catalog.indirection.reset_terminus_class + end + it "should prepare for the run" do @agent.expects(:prepare) diff --git a/spec/unit/face/node_spec.rb b/spec/unit/face/node_spec.rb index 6f6edc6cc..4c6b80137 100755 --- a/spec/unit/face/node_spec.rb +++ b/spec/unit/face/node_spec.rb @@ -3,6 +3,10 @@ require 'spec_helper' require 'puppet/face' describe Puppet::Face[:node, '0.0.1'] do + after :all do + Puppet::SSL::Host.ca_location = :none + end + describe '#cleanup' do it "should clean everything" do { diff --git a/spec/unit/type/file_spec.rb b/spec/unit/type/file_spec.rb index 65c7a091c..0041ce9f2 100755 --- a/spec/unit/type/file_spec.rb +++ b/spec/unit/type/file_spec.rb @@ -1185,4 +1185,10 @@ describe Puppet::Type.type(:file) do @file[:checksum].should be :md5lite end end + + describe ".instances" do + it 'should return an empty array' do + Puppet::Type::File.instances.should == [] + end + end end diff --git a/spec/unit/util/suidmanager_spec.rb b/spec/unit/util/suidmanager_spec.rb new file mode 100755 index 000000000..fc70e1718 --- /dev/null +++ b/spec/unit/util/suidmanager_spec.rb @@ -0,0 +1,210 @@ +#!/usr/bin/env rspec + +require 'spec_helper' + +describe Puppet::Util::SUIDManager do + let :user do + Puppet::Type.type(:user).new(:name => 'name', :uid => 42, :gid => 42) + end + + let :xids do + Hash.new {|h,k| 0} + end + + before :each do + Puppet::Util::SUIDManager.stubs(:convert_xid).returns(42) + Puppet::Util::SUIDManager.stubs(:initgroups) + + [:euid, :egid, :uid, :gid, :groups].each do |id| + Process.stubs("#{id}=").with {|value| xids[id] = value} + end + end + + describe "#uid" do + it "should allow setting euid/egid" do + Puppet::Util::SUIDManager.egid = user[:gid] + Puppet::Util::SUIDManager.euid = user[:uid] + + xids[:egid].should == user[:gid] + xids[:euid].should == user[:uid] + end + end + + describe "#asuser" do + it "should set euid/egid when root" do + Process.stubs(:uid).returns(0) + + Process.stubs(:egid).returns(51) + Process.stubs(:euid).returns(50) + + Puppet::Util::SUIDManager.stubs(:convert_xid).with(:gid, 51).returns(51) + Puppet::Util::SUIDManager.stubs(:convert_xid).with(:uid, 50).returns(50) + + yielded = false + Puppet::Util::SUIDManager.asuser(user[:uid], user[:gid]) do + xids[:egid].should == user[:gid] + xids[:euid].should == user[:uid] + yielded = true + end + + xids[:egid].should == 51 + xids[:euid].should == 50 + + # It's possible asuser could simply not yield, so the assertions in the + # block wouldn't fail. So verify those actually got checked. + yielded.should be_true + end + + it "should not get or set euid/egid when not root" do + Process.stubs(:uid).returns(1) + + Process.stubs(:egid).returns(51) + Process.stubs(:euid).returns(50) + + Puppet::Util::SUIDManager.asuser(user[:uid], user[:gid]) {} + + xids.should be_empty + end + end + + describe "#change_group" do + describe "when changing permanently" do + it "should try to change_privilege if it is supported" do + Process::GID.expects(:change_privilege).with do |gid| + Process.gid = gid + Process.egid = gid + end + + Puppet::Util::SUIDManager.change_group(42, true) + + xids[:egid].should == 42 + xids[:gid].should == 42 + end + + it "should change both egid and gid if change_privilege isn't supported" do + Process::GID.stubs(:change_privilege).raises(NotImplementedError) + + Puppet::Util::SUIDManager.change_group(42, true) + + xids[:egid].should == 42 + xids[:gid].should == 42 + end + end + + describe "when changing temporarily" do + it "should change only egid" do + Puppet::Util::SUIDManager.change_group(42, false) + + xids[:egid].should == 42 + xids[:gid].should == 0 + end + end + end + + describe "#change_user" do + describe "when changing permanently" do + it "should try to change_privilege if it is supported" do + Process::UID.expects(:change_privilege).with do |uid| + Process.uid = uid + Process.euid = uid + end + + Puppet::Util::SUIDManager.change_user(42, true) + + xids[:euid].should == 42 + xids[:uid].should == 42 + end + + it "should change euid and uid and groups if change_privilege isn't supported" do + Process::UID.stubs(:change_privilege).raises(NotImplementedError) + + Puppet::Util::SUIDManager.expects(:initgroups).with(42) + + Puppet::Util::SUIDManager.change_user(42, true) + + xids[:euid].should == 42 + xids[:uid].should == 42 + end + end + + describe "when changing temporarily" do + it "should change only euid and groups" do + Puppet::Util::SUIDManager.change_user(42, false) + + xids[:euid].should == 42 + xids[:uid].should == 0 + end + + it "should set euid before groups if changing to root" do + Process.stubs(:euid).returns 50 + + when_not_root = sequence 'when_not_root' + + Process.expects(:euid=).in_sequence(when_not_root) + Puppet::Util::SUIDManager.expects(:initgroups).in_sequence(when_not_root) + + Puppet::Util::SUIDManager.change_user(0, false) + end + + it "should set groups before euid if changing from root" do + Process.stubs(:euid).returns 0 + + when_root = sequence 'when_root' + + Puppet::Util::SUIDManager.expects(:initgroups).in_sequence(when_root) + Process.expects(:euid=).in_sequence(when_root) + + Puppet::Util::SUIDManager.change_user(50, false) + end + end + end + + describe "when running commands" do + before :each do + # We want to make sure $CHILD_STATUS is set + Kernel.system '' if $CHILD_STATUS.nil? + end + + describe "with #system" do + it "should set euid/egid when root" do + Process.stubs(:uid).returns(0) + Process.stubs(:egid).returns(51) + Process.stubs(:euid).returns(50) + + Puppet::Util::SUIDManager.stubs(:convert_xid).with(:gid, 51).returns(51) + Puppet::Util::SUIDManager.stubs(:convert_xid).with(:uid, 50).returns(50) + + Puppet::Util::SUIDManager.expects(:change_group).with(user[:uid]) + Puppet::Util::SUIDManager.expects(:change_user).with(user[:uid]) + + Puppet::Util::SUIDManager.expects(:change_group).with(51) + Puppet::Util::SUIDManager.expects(:change_user).with(50) + + Kernel.expects(:system).with('blah') + Puppet::Util::SUIDManager.system('blah', user[:uid], user[:gid]) + end + + it "should not get or set euid/egid when not root" do + Process.stubs(:uid).returns(1) + Kernel.expects(:system).with('blah') + + Puppet::Util::SUIDManager.system('blah', user[:uid], user[:gid]) + + xids.should be_empty + end + end + + describe "with #run_and_capture" do + it "should capture the output and return process status" do + Puppet::Util. + expects(:execute). + with('yay', :combine => true, :failonfail => false, :uid => user[:uid], :gid => user[:gid]). + returns('output') + output = Puppet::Util::SUIDManager.run_and_capture 'yay', user[:uid], user[:gid] + + output.first.should == 'output' + output.last.should be_a(Process::Status) + end + end + end +end diff --git a/test/puppet/tc_suidmanager.rb b/test/puppet/tc_suidmanager.rb deleted file mode 100755 index 2f4cb40da..000000000 --- a/test/puppet/tc_suidmanager.rb +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env ruby - -require File.expand_path(File.dirname(__FILE__) + '/../lib/puppettest') - -require 'puppet' -require 'puppettest' -require 'test/unit' -require 'mocha' - -class TestSUIDManager < Test::Unit::TestCase - include PuppetTest - - def setup - the_id = 42 - Puppet::Util::SUIDManager.stubs(:convert_xid).returns(the_id) - Puppet::Util::SUIDManager.stubs(:initgroups) - @user = stub('user', :uid => the_id, :gid => the_id, :name => 'name') - super - end - - def test_metaprogramming_function_additions - # NOTE: the way that we are dynamically generating the methods in - # SUIDManager for the UID/GID calls was causing problems due to the - # modification of a closure. Should the bug rear itself again, this - # test will fail. - Process.expects(:uid).times(2) - - assert_nothing_raised do - Puppet::Util::SUIDManager.uid - Puppet::Util::SUIDManager.uid - end - end - - def test_id_set - Process.expects(:euid=).with(@user.uid) - Process.expects(:egid=).with(@user.gid) - - assert_nothing_raised do - Puppet::Util::SUIDManager.egid = @user.gid - Puppet::Util::SUIDManager.euid = @user.uid - end - end - - def test_utiluid - assert_not_equal(nil, Puppet::Util.uid(nonrootuser.name)) - end - - def test_asuser_as_root - Process.stubs(:uid).returns(0) - expects_id_set_and_revert @user.uid, @user.gid - Puppet::Util::SUIDManager.asuser @user.uid, @user.gid do end - rescue Errno::EPERM - end - - def test_asuser_as_nonroot - Process.stubs(:uid).returns(1) - expects_no_id_set - Puppet::Util::SUIDManager.asuser @user.uid, @user.gid do end - end - - - def test_system_as_root - Process.stubs(:uid).returns(0) - set_exit_status! - expects_id_set_and_revert @user.uid, @user.gid - Kernel.expects(:system).with('blah') - Puppet::Util::SUIDManager.system('blah', @user.uid, @user.gid) - end - - def test_system_as_nonroot - Process.stubs(:uid).returns(1) - set_exit_status! - expects_no_id_set - Kernel.expects(:system).with('blah') - Puppet::Util::SUIDManager.system('blah', @user.uid, @user.gid) - end - - def test_run_and_capture - if (RUBY_VERSION <=> "1.8.4") < 0 - warn "Cannot run this test on ruby < 1.8.4" - else - set_exit_status! - Puppet::Util. - expects(:execute). - with('yay',:combine => true, :failonfail => false, :uid => @user.uid, :gid => @user.gid). - returns('output') - output = Puppet::Util::SUIDManager.run_and_capture 'yay', @user.uid, @user.gid - - assert_equal 'output', output.first - assert_kind_of Process::Status, output.last - end - end - - private - - def expects_id_set_and_revert(uid, gid) - Process.stubs(:groups=) - Process.expects(:euid).returns(99997) - Process.expects(:egid).returns(99996) - - Process.expects(:euid=).with(uid) - Process.expects(:egid=).with(gid) - - Process.expects(:euid=).with(99997) - Process.expects(:egid=).with(99996) - end - - def expects_no_id_set - Process.expects(:egid).never - Process.expects(:euid).never - Process.expects(:egid=).never - Process.expects(:euid=).never - end - - def set_exit_status! - # We want to make sure $CHILD_STATUS is set, this is the only way I know how. - Kernel.system '' if $CHILD_STATUS.nil? - end -end - |