diff options
author | Josh Cooper <josh@puppetlabs.com> | 2011-08-18 10:34:18 -0700 |
---|---|---|
committer | Josh Cooper <josh@puppetlabs.com> | 2011-08-22 15:06:11 -0700 |
commit | 2ac87905708ddbc44d212e10e34d72cad09e3271 (patch) | |
tree | 9907686fa4f90f5ce4379f982808498dd3156943 | |
parent | ccdd043ab309ca382dc949612d7efe3562adf5c5 (diff) | |
download | puppet-2ac87905708ddbc44d212e10e34d72cad09e3271.tar.gz puppet-2ac87905708ddbc44d212e10e34d72cad09e3271.tar.xz puppet-2ac87905708ddbc44d212e10e34d72cad09e3271.zip |
(#8662) Fix Puppet.features.root? on Windows
This commit changes Puppet::Util::SUIDManager.root? (and
Puppet.features.root?) to only return true if the user is running with
elevated privileges (granted via UAC). If this check fails because
elevated privileges are not supported, e.g. pre-Vista, then we fall
back to checking if the user is a member of the builtin Administrators
group.
This means if you are logged in as Administrator on 2008,
Puppet.features.root? will return false, unless you are explicitly
running puppet as an administrator, e.g.
runas /user:Administrator "puppet apply manifest.pp"
This commit also adds tests to ensure SUIDManager.asuser is a no-op on
Windows, since Windows does not (easily) support switching user
contexts without providing a password.
-rw-r--r-- | lib/puppet/util/suidmanager.rb | 15 | ||||
-rwxr-xr-x | spec/unit/util/suidmanager_spec.rb | 89 |
2 files changed, 103 insertions, 1 deletions
diff --git a/lib/puppet/util/suidmanager.rb b/lib/puppet/util/suidmanager.rb index 697bce111..d2772002e 100644 --- a/lib/puppet/util/suidmanager.rb +++ b/lib/puppet/util/suidmanager.rb @@ -37,7 +37,20 @@ module Puppet::Util::SUIDManager module_function :groups= def self.root? - Process.uid == 0 + return Process.uid == 0 unless Puppet.features.microsoft_windows? + + require 'sys/admin' + require 'win32/security' + + # if Vista or later, check for unrestricted process token + begin + return Win32::Security.elevated_security? + rescue Win32::Security::Error => e + raise e unless e.to_s =~ /Incorrect function/i + end + + group = Sys::Admin.get_group("Administrators", :sid => Win32::Security::SID::BuiltinAdministrators) + group and group.members.index(Sys::Admin.get_login) != nil end # Runs block setting uid and gid if provided then restoring original ids diff --git a/spec/unit/util/suidmanager_spec.rb b/spec/unit/util/suidmanager_spec.rb index abfe3f723..474d0b2a2 100755 --- a/spec/unit/util/suidmanager_spec.rb +++ b/spec/unit/util/suidmanager_spec.rb @@ -66,6 +66,14 @@ describe Puppet::Util::SUIDManager do xids.should be_empty end + + it "should not get or set euid/egid on Windows" do + Puppet.features.stubs(:microsoft_windows?).returns true + + Puppet::Util::SUIDManager.asuser(user[:uid], user[:gid]) {} + + xids.should be_empty + end end describe "#change_group" do @@ -195,6 +203,15 @@ describe Puppet::Util::SUIDManager do xids.should be_empty end + + it "should not get or set euid/egid on Windows" do + Puppet.features.stubs(:microsoft_windows?).returns true + 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 @@ -210,4 +227,76 @@ describe Puppet::Util::SUIDManager do end end end + + describe "#root?" do + describe "on POSIX systems" do + before :each do + Puppet.features.stubs(:posix?).returns(true) + Puppet.features.stubs(:microsoft_windows?).returns(false) + end + + it "should be root if uid is 0" do + Process.stubs(:uid).returns(0) + + Puppet::Util::SUIDManager.should be_root + end + + it "should not be root if uid is not 0" do + Process.stubs(:uid).returns(1) + + Puppet::Util::SUIDManager.should_not be_root + end + end + + describe "on Microsoft Windows", :if => Puppet.features.microsoft_windows? do + describe "2003 without UAC" do + it "should be root if user is a member of the Administrators group" do + Win32::Security.stubs(:elevated_security?).raises(Win32::Security::Error, "Incorrect function.") + Sys::Admin.stubs(:get_login).returns("Administrator") + Sys::Group.stubs(:members).returns(%w[Administrator]) + + Puppet::Util::SUIDManager.should be_root + end + + it "should not be root if the process is running as Guest" do + Win32::Security.stubs(:elevated_security?).raises(Win32::Security::Error, "Incorrect function.") + Sys::Admin.stubs(:get_login).returns("Guest") + Sys::Group.stubs(:members).returns([]) + + Puppet::Util::SUIDManager.should_not be_root + end + + it "should raise an exception if the process fails to open the process token" do + Win32::Security.stubs(:elevated_security?).raises(Win32::Security::Error, "Access denied.") + Sys::Admin.stubs(:get_login).returns("Administrator") + Sys::Group.expects(:members).never + + lambda { Puppet::Util::SUIDManager.should raise_error(Win32::Security::Error, /Access denied./) } + end + end + + describe "2008 with UAC" do + it "should be root if user is running with elevated privileges" do + Win32::Security.stubs(:elevated_security?).returns(true) + Sys::Admin.expects(:get_login).never + + Puppet::Util::SUIDManager.should be_root + end + + it "should not be root if user is not running with elevated privileges" do + Win32::Security.stubs(:elevated_security?).returns(false) + Sys::Admin.expects(:get_login).never + + Puppet::Util::SUIDManager.should_not be_root + end + + it "should raise an exception if the process fails to open the process token" do + Win32::Security.stubs(:elevated_security?).raises(Win32::Security::Error, "Access denied.") + Sys::Admin.expects(:get_login).never + + lambda { Puppet::Util::SUIDManager.should raise_error(Win32::Security::Error, /Access denied./) } + end + end + end + end end |