summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Lewis <nick@puppetlabs.com>2011-08-22 17:06:44 -0700
committerNick Lewis <nick@puppetlabs.com>2011-08-22 17:06:44 -0700
commit630ec36089e2224fba99b76d76eaf904af13e4d6 (patch)
treea04dff02eb8f296f7a56952cade0621848280288
parent4684db12b1ca27df4d612fb1a54b7be43f54a6a8 (diff)
parent0f207a8ea61205ba6b47e8da429ab3887b3cda4d (diff)
downloadpuppet-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.rb54
-rw-r--r--lib/puppet/util/settings.rb1
-rw-r--r--lib/puppet/util/settings/file_setting.rb3
-rw-r--r--lib/puppet/util/suidmanager.rb15
-rwxr-xr-xspec/unit/util/settings/file_setting_spec.rb22
-rwxr-xr-xspec/unit/util/settings_spec.rb19
-rwxr-xr-xspec/unit/util/suidmanager_spec.rb89
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