diff options
author | Adam Edwards <adamed@opscode.com> | 2015-12-12 23:08:24 -0800 |
---|---|---|
committer | nimisha <nimisha.sharad@msystechnologies.com> | 2017-02-02 18:00:23 +0530 |
commit | 8a68a2a8bd043ae0c75d2c21c0b75259942039e4 (patch) | |
tree | 50e747bb0934744c2d94e838bf954b031fea9d27 /lib/chef | |
parent | 8ed11241ca1236d16a14e5bb32ef1ff16fabfeb9 (diff) | |
download | chef-8a68a2a8bd043ae0c75d2c21c0b75259942039e4.tar.gz |
Windows alternate user support for execute resources
Diffstat (limited to 'lib/chef')
-rw-r--r-- | lib/chef/provider/execute.rb | 19 | ||||
-rw-r--r-- | lib/chef/provider/powershell_script.rb | 8 | ||||
-rw-r--r-- | lib/chef/provider/script.rb | 38 | ||||
-rw-r--r-- | lib/chef/resource/execute.rb | 24 |
4 files changed, 81 insertions, 8 deletions
diff --git a/lib/chef/provider/execute.rb b/lib/chef/provider/execute.rb index 45f0ad5488..c8e3d2732b 100644 --- a/lib/chef/provider/execute.rb +++ b/lib/chef/provider/execute.rb @@ -16,18 +16,25 @@ # limitations under the License. # -require "chef/log" -require "chef/provider" -require "forwardable" +require 'chef/log' +require 'chef/provider' +require 'forwardable' +require 'chef/mixin/user_identity' class Chef class Provider class Execute < Chef::Provider extend Forwardable + include Chef::Mixin::UserIdentity + provides :execute - def_delegators :@new_resource, :command, :returns, :environment, :user, :group, :cwd, :umask, :creates + def_delegators :@new_resource, :command, :returns, :environment, :user, :domain, :password, :group, :cwd, :umask, :creates + + def initialize(new_resource, run_context) + super + end def load_current_resource current_resource = Chef::Resource::Execute.new(new_resource.name) @@ -52,6 +59,7 @@ class Chef end def action_run + validate_identity(new_resource.user, new_resource.password, new_resource.domain) if creates && sentinel_file.exist? Chef::Log.debug("#{new_resource} sentinel file #{sentinel_file} exists - nothing to do") return false @@ -92,6 +100,8 @@ class Chef opts[:returns] = returns if returns opts[:environment] = environment if environment opts[:user] = user if user + opts[:domain] = domain if domain + opts[:password] = password if password opts[:group] = group if group opts[:cwd] = cwd if cwd opts[:umask] = umask if umask @@ -120,6 +130,7 @@ class Chef ( cwd && creates_relative? ) ? ::File.join(cwd, creates) : creates )) end + end end end diff --git a/lib/chef/provider/powershell_script.rb b/lib/chef/provider/powershell_script.rb index ab85ec35ac..0cace362df 100644 --- a/lib/chef/provider/powershell_script.rb +++ b/lib/chef/provider/powershell_script.rb @@ -149,6 +149,14 @@ EOH <<-EOH # Chef Client wrapper for powershell_script resources +# In rare cases, such as when PowerShell is executed +# as an alternate user, the new-variable cmdlet is not +# available, so import it just in case +if ( get-module -ListAvailable Microsoft.PowerShell.Utility ) +{ + Import-Module Microsoft.PowerShell.Utility +} + # LASTEXITCODE can be uninitialized -- make it explictly 0 # to avoid incorrect detection of failure (non-zero) codes $global:LASTEXITCODE = 0 diff --git a/lib/chef/provider/script.rb b/lib/chef/provider/script.rb index 6ca4e9f6f3..9aee6fe442 100644 --- a/lib/chef/provider/script.rb +++ b/lib/chef/provider/script.rb @@ -16,9 +16,10 @@ # limitations under the License. # -require "tempfile" -require "chef/provider/execute" -require "forwardable" +require 'tempfile' +require 'chef/provider/execute' +require 'chef/win32/security' if Chef::Platform.windows? +require 'forwardable' class Chef class Provider @@ -69,7 +70,36 @@ class Chef # FileUtils itself implements a no-op if +user+ or +group+ are nil # You can prove this by running FileUtils.chown(nil,nil,'/tmp/file') # as an unprivileged user. - FileUtils.chown(new_resource.user, new_resource.group, script_file.path) + if ! Chef::Platform.windows? + FileUtils.chown(new_resource.user, new_resource.group, script_file.path) + else + grant_alternate_user_read_access + end + end + + def grant_alternate_user_read_access + return if new_resource.user.nil? + + # Duplicate the script file's existing DACL + # so we can add an ACE later + securable_object = Chef::ReservedNames::Win32::Security::SecurableObject.new(script_file.path) + aces = securable_object.security_descriptor.dacl.reduce([]) { | result, current | result.push(current) } + + username = new_resource.user + + if new_resource.domain + username = new_resource.domain + '\\' + new_resource.user + end + + # Create an ACE that allows the alternate user read access to the script + # file so it can be read and executed. + user_sid = Chef::ReservedNames::Win32::Security::SID.from_account(username) + read_ace = Chef::ReservedNames::Win32::Security::ACE.access_allowed(user_sid, Chef::ReservedNames::Win32::API::Security::GENERIC_READ | Chef::ReservedNames::Win32::API::Security::GENERIC_EXECUTE, 0) + aces.push(read_ace) + acl = Chef::ReservedNames::Win32::Security::ACL.create(aces) + + # This actually applies the modified DACL to the file + securable_object.dacl = acl end def script_file diff --git a/lib/chef/resource/execute.rb b/lib/chef/resource/execute.rb index 1a56607267..08664e9a7a 100644 --- a/lib/chef/resource/execute.rb +++ b/lib/chef/resource/execute.rb @@ -143,6 +143,30 @@ class Chef ) end + def domain(arg=nil) + set_or_return( + :domain, + arg, + :kind_of => [ String ] + ) + end + + def password(arg=nil) + set_or_return( + :password, + arg, + :kind_of => [ String ] + ) + end + + def sensitive(args=nil) + if ! password.nil? + true + else + super + end + end + def self.set_guard_inherited_attributes(*inherited_attributes) @class_inherited_attributes = inherited_attributes end |