diff options
author | Nick Lewis <nick@puppetlabs.com> | 2011-08-22 17:06:44 -0700 |
---|---|---|
committer | Nick Lewis <nick@puppetlabs.com> | 2011-08-22 17:06:44 -0700 |
commit | 630ec36089e2224fba99b76d76eaf904af13e4d6 (patch) | |
tree | a04dff02eb8f296f7a56952cade0621848280288 | |
parent | 4684db12b1ca27df4d612fb1a54b7be43f54a6a8 (diff) | |
parent | 0f207a8ea61205ba6b47e8da429ab3887b3cda4d (diff) | |
download | puppet-630ec36089e2224fba99b76d76eaf904af13e4d6.tar.gz puppet-630ec36089e2224fba99b76d76eaf904af13e4d6.tar.xz puppet-630ec36089e2224fba99b76d76eaf904af13e4d6.zip |
Merge pull request #53 from joshcooper/ticket/2.7.x/8662-root-on-windows
Ticket/2.7.x/8662 root on windows
-rw-r--r-- | lib/puppet/feature/base.rb | 54 | ||||
-rw-r--r-- | lib/puppet/util/settings.rb | 1 | ||||
-rw-r--r-- | lib/puppet/util/settings/file_setting.rb | 3 | ||||
-rw-r--r-- | lib/puppet/util/suidmanager.rb | 15 | ||||
-rwxr-xr-x | spec/unit/util/settings/file_setting_spec.rb | 22 | ||||
-rwxr-xr-x | spec/unit/util/settings_spec.rb | 19 | ||||
-rwxr-xr-x | spec/unit/util/suidmanager_spec.rb | 89 |
7 files changed, 175 insertions, 28 deletions
diff --git a/lib/puppet/feature/base.rb b/lib/puppet/feature/base.rb index 2eddadb7a..cecc1b9ad 100644 --- a/lib/puppet/feature/base.rb +++ b/lib/puppet/feature/base.rb @@ -2,6 +2,34 @@ require 'puppet/util/feature' # Add the simple features, all in one file. +# Order is important as some features depend on others + +# We have a syslog implementation +Puppet.features.add(:syslog, :libs => ["syslog"]) + +# We can use POSIX user functions +Puppet.features.add(:posix) do + require 'etc' + Etc.getpwuid(0) != nil && Puppet.features.syslog? +end + +# We can use Microsoft Windows functions +Puppet.features.add(:microsoft_windows) do + begin + require 'sys/admin' + require 'win32/process' + require 'win32/dir' + require 'win32/service' + require 'win32ole' + require 'win32/api' + true + rescue LoadError => err + warn "Cannot run on Microsoft Windows without the sys-admin, win32-process, win32-dir & win32-service gems: #{err}" unless Puppet.features.posix? + end +end + +raise Puppet::Error,"Cannot determine basic system flavour" unless Puppet.features.posix? or Puppet.features.microsoft_windows? + # We've got LDAP available. Puppet.features.add(:ldap, :libs => ["ldap"]) @@ -30,32 +58,6 @@ Puppet.features.add(:rrd, :libs => ["RRD"]) # We have OpenSSL Puppet.features.add(:openssl, :libs => ["openssl"]) -# We have a syslog implementation -Puppet.features.add(:syslog, :libs => ["syslog"]) - -# We can use POSIX user functions -Puppet.features.add(:posix) do - require 'etc' - Etc.getpwuid(0) != nil && Puppet.features.syslog? -end - -# We can use Microsoft Windows functions -Puppet.features.add(:microsoft_windows) do - begin - require 'sys/admin' - require 'win32/process' - require 'win32/dir' - require 'win32/service' - require 'win32ole' - require 'win32/api' - true - rescue LoadError => err - warn "Cannot run on Microsoft Windows without the sys-admin, win32-process, win32-dir & win32-service gems: #{err}" unless Puppet.features.posix? - end -end - -raise Puppet::Error,"Cannot determine basic system flavour" unless Puppet.features.posix? or Puppet.features.microsoft_windows? - # We have CouchDB Puppet.features.add(:couchdb, :libs => ["couchrest"]) diff --git a/lib/puppet/util/settings.rb b/lib/puppet/util/settings.rb index caaf61b7b..3039a7b0a 100644 --- a/lib/puppet/util/settings.rb +++ b/lib/puppet/util/settings.rb @@ -780,6 +780,7 @@ if @config.include?(:run_mode) # Create the transportable objects for users and groups. def add_user_resources(catalog, sections) return unless Puppet.features.root? + return if Puppet.features.microsoft_windows? return unless self[:mkusers] @config.each do |name, setting| diff --git a/lib/puppet/util/settings/file_setting.rb b/lib/puppet/util/settings/file_setting.rb index 0fa65d846..f02a0c547 100644 --- a/lib/puppet/util/settings/file_setting.rb +++ b/lib/puppet/util/settings/file_setting.rb @@ -93,7 +93,8 @@ class Puppet::Util::Settings::FileSetting < Puppet::Util::Settings::Setting if Puppet[:manage_internal_file_permissions] resource[:mode] = self.mode if self.mode - if Puppet.features.root? + # REMIND fails on Windows because chown/chgrp functionality not supported yet + if Puppet.features.root? and !Puppet.features.microsoft_windows? resource[:owner] = self.owner if self.owner resource[:group] = self.group if self.group end 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/settings/file_setting_spec.rb b/spec/unit/util/settings/file_setting_spec.rb index 01d891f08..6344cf1b5 100755 --- a/spec/unit/util/settings/file_setting_spec.rb +++ b/spec/unit/util/settings/file_setting_spec.rb @@ -189,6 +189,8 @@ describe Puppet::Util::Settings::FileSetting do it "should set the owner if running as root and the owner is provided" do Puppet.features.expects(:root?).returns true + Puppet.features.stubs(:microsoft_windows?).returns false + @file.stubs(:owner).returns "foo" @file.to_resource[:owner].should == "foo" end @@ -203,6 +205,8 @@ describe Puppet::Util::Settings::FileSetting do it "should set the group if running as root and the group is provided" do Puppet.features.expects(:root?).returns true + Puppet.features.stubs(:microsoft_windows?).returns false + @file.stubs(:group).returns "foo" @file.to_resource[:group].should == "foo" end @@ -218,16 +222,34 @@ describe Puppet::Util::Settings::FileSetting do it "should not set owner if not running as root" do Puppet.features.expects(:root?).returns false + Puppet.features.stubs(:microsoft_windows?).returns false @file.stubs(:owner).returns "foo" @file.to_resource[:owner].should be_nil end it "should not set group if not running as root" do Puppet.features.expects(:root?).returns false + Puppet.features.stubs(:microsoft_windows?).returns false @file.stubs(:group).returns "foo" @file.to_resource[:group].should be_nil end + describe "on Microsoft Windows systems" do + before :each do + Puppet.features.stubs(:microsoft_windows?).returns true + end + + it "should not set owner" do + @file.stubs(:owner).returns "foo" + @file.to_resource[:owner].should be_nil + end + + it "should not set group" do + @file.stubs(:group).returns "foo" + @file.to_resource[:group].should be_nil + end + end + it "should set :ensure to the file type" do @file.expects(:type).returns :directory @file.to_resource[:ensure].should == :directory diff --git a/spec/unit/util/settings_spec.rb b/spec/unit/util/settings_spec.rb index 76f229c0f..69c117f28 100755 --- a/spec/unit/util/settings_spec.rb +++ b/spec/unit/util/settings_spec.rb @@ -720,9 +720,28 @@ describe Puppet::Util::Settings do @settings.to_catalog end + describe "on Microsoft Windows" do + before :each do + Puppet.features.stubs(:root?).returns true + Puppet.features.stubs(:microsoft_windows?).returns true + + @settings.setdefaults :foo, :mkusers => [true, "e"], :user => ["suser", "doc"], :group => ["sgroup", "doc"] + @settings.setdefaults :other, :otherdir => {:default => "/otherdir", :desc => "a", :owner => "service", :group => "service"} + + @catalog = @settings.to_catalog + end + + it "it should not add users and groups to the catalog" do + @catalog.resource(:user, "suser").should be_nil + @catalog.resource(:group, "sgroup").should be_nil + end + end + describe "when adding users and groups to the catalog" do before do Puppet.features.stubs(:root?).returns true + Puppet.features.stubs(:microsoft_windows?).returns false + @settings.setdefaults :foo, :mkusers => [true, "e"], :user => ["suser", "doc"], :group => ["sgroup", "doc"] @settings.setdefaults :other, :otherdir => {:default => "/otherdir", :desc => "a", :owner => "service", :group => "service"} 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 |