summaryrefslogtreecommitdiff
path: root/lib/chef
diff options
context:
space:
mode:
authorAdam Edwards <adamed@opscode.com>2015-12-12 23:08:24 -0800
committernimisha <nimisha.sharad@msystechnologies.com>2017-02-02 18:00:23 +0530
commit8a68a2a8bd043ae0c75d2c21c0b75259942039e4 (patch)
tree50e747bb0934744c2d94e838bf954b031fea9d27 /lib/chef
parent8ed11241ca1236d16a14e5bb32ef1ff16fabfeb9 (diff)
downloadchef-8a68a2a8bd043ae0c75d2c21c0b75259942039e4.tar.gz
Windows alternate user support for execute resources
Diffstat (limited to 'lib/chef')
-rw-r--r--lib/chef/provider/execute.rb19
-rw-r--r--lib/chef/provider/powershell_script.rb8
-rw-r--r--lib/chef/provider/script.rb38
-rw-r--r--lib/chef/resource/execute.rb24
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