chef 13.3.42-universal-mingw32 → 13.4.19-universal-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/VERSION +1 -1
  4. data/lib/.DS_Store +0 -0
  5. data/lib/chef/.DS_Store +0 -0
  6. data/lib/chef/knife/core/ui.rb +1 -1
  7. data/lib/chef/mash.rb +6 -0
  8. data/lib/chef/mixin/deep_merge.rb +1 -1
  9. data/lib/chef/mixin/user_context.rb +52 -0
  10. data/lib/chef/node/attribute.rb +80 -14
  11. data/lib/chef/node/immutable_collections.rb +16 -19
  12. data/lib/chef/provider/apt_repository.rb +12 -10
  13. data/lib/chef/provider/git.rb +20 -3
  14. data/lib/chef/provider/ifconfig/redhat.rb +4 -0
  15. data/lib/chef/provider/launchd.rb +20 -0
  16. data/lib/chef/provider/package/dnf.rb +3 -1
  17. data/lib/chef/provider/remote_file.rb +19 -0
  18. data/lib/chef/provider/remote_file/fetcher.rb +3 -0
  19. data/lib/chef/provider/remote_file/network_file.rb +18 -5
  20. data/lib/chef/provider/service/macosx.rb +4 -3
  21. data/lib/chef/provider/windows_path.rb +62 -0
  22. data/lib/chef/provider/zypper_repository.rb +1 -1
  23. data/lib/chef/providers.rb +1 -0
  24. data/lib/chef/resource.rb +5 -1
  25. data/lib/chef/resource/apt_repository.rb +1 -1
  26. data/lib/chef/resource/ifconfig.rb +36 -0
  27. data/lib/chef/resource/remote_file.rb +60 -0
  28. data/lib/chef/resource/windows_path.rb +41 -0
  29. data/lib/chef/resource/zypper_repository.rb +1 -0
  30. data/lib/chef/resources.rb +1 -0
  31. data/lib/chef/shell.rb +1 -0
  32. data/lib/chef/shell/shell_session.rb +4 -4
  33. data/lib/chef/util/windows/logon_session.rb +126 -0
  34. data/lib/chef/version.rb +4 -3
  35. data/lib/chef/win32/api/security.rb +2 -0
  36. data/spec/.DS_Store +0 -0
  37. data/spec/data/nodes/Timothys-MacBook-Pro.local.json +3 -0
  38. data/spec/functional/.DS_Store +0 -0
  39. data/spec/functional/mixin/user_context_spec.rb +117 -0
  40. data/spec/functional/resource/remote_file_spec.rb +171 -0
  41. data/spec/functional/resource/windows_path_spec.rb +64 -0
  42. data/spec/support/.DS_Store +0 -0
  43. data/spec/unit/.DS_Store +0 -0
  44. data/spec/unit/knife/client_delete_spec.rb +1 -1
  45. data/spec/unit/mixin/user_context_spec.rb +109 -0
  46. data/spec/unit/node/immutable_collections_spec.rb +12 -4
  47. data/spec/unit/node_spec.rb +7 -0
  48. data/spec/unit/provider/git_spec.rb +55 -0
  49. data/spec/unit/provider/ifconfig/redhat_spec.rb +8 -0
  50. data/spec/unit/provider/remote_file/fetcher_spec.rb +1 -0
  51. data/spec/unit/provider/remote_file/network_file_spec.rb +7 -2
  52. data/spec/unit/provider/service/macosx_spec.rb +4 -1
  53. data/spec/unit/provider/windows_path_spec.rb +65 -0
  54. data/spec/unit/resource/windows_path_spec.rb +38 -0
  55. data/spec/unit/resource_spec.rb +8 -0
  56. data/spec/unit/shell/shell_session_spec.rb +82 -58
  57. data/spec/unit/util/windows/logon_session_spec.rb +284 -0
  58. data/tasks/maintainers.rb +3 -3
  59. metadata +22 -5
@@ -35,10 +35,12 @@ class Chef
35
35
  use_multipackage_api
36
36
  use_package_name_for_source
37
37
 
38
- provides :package, platform_family: %w{rhel fedora amazon} do
38
+ provides :package, platform_family: %w{fedora amazon} do
39
39
  which("dnf") && shell_out("rpm -q dnf").stdout =~ /^dnf-[1-9]/
40
40
  end
41
41
 
42
+ provides :package, platform_family: %w{rhel}, platform_version: ">= 8"
43
+
42
44
  provides :dnf_package, os: "linux"
43
45
 
44
46
  #
@@ -29,6 +29,25 @@ class Chef
29
29
  super
30
30
  end
31
31
 
32
+ def define_resource_requirements
33
+ [ new_resource.remote_user, new_resource.remote_domain,
34
+ new_resource.remote_password ].each do |prop|
35
+ requirements.assert(:all_actions) do |a|
36
+ a.assertion do
37
+ if prop
38
+ node[:platform_family] == "windows"
39
+ else
40
+ true
41
+ end
42
+ end
43
+ a.failure_message Chef::Exceptions::UnsupportedPlatform, "'remote_user', 'remote_domain' and 'remote_password' properties are supported only for Windows platform"
44
+ a.whyrun("Assuming that the platform is Windows while passing 'remote_user', 'remote_domain' and 'remote_password' properties")
45
+ end
46
+ end
47
+
48
+ super
49
+ end
50
+
32
51
  def load_current_resource
33
52
  @current_resource = Chef::Resource::RemoteFile.new(new_resource.name)
34
53
  super
@@ -24,6 +24,9 @@ class Chef
24
24
 
25
25
  def self.for_resource(uri, new_resource, current_resource)
26
26
  if network_share?(uri)
27
+ if !Chef::Platform.windows?
28
+ raise Exceptions::UnsupportedPlatform, "Fetching the file on a network share is supported only on the Windows platform. Please change your source: #{uri}"
29
+ end
27
30
  Chef::Provider::RemoteFile::NetworkFile.new(uri, new_resource, current_resource)
28
31
  else
29
32
  case uri.scheme
@@ -19,14 +19,18 @@
19
19
  require "uri"
20
20
  require "tempfile"
21
21
  require "chef/provider/remote_file"
22
+ require "chef/mixin/user_context"
22
23
 
23
24
  class Chef
24
25
  class Provider
25
26
  class RemoteFile
26
27
  class NetworkFile
28
+ include Chef::Mixin::UserContext
27
29
 
28
30
  attr_reader :new_resource
29
31
 
32
+ TRANSFER_CHUNK_SIZE = 1048576
33
+
30
34
  def initialize(source, new_resource, current_resource)
31
35
  @new_resource = new_resource
32
36
  @source = source
@@ -35,13 +39,22 @@ class Chef
35
39
  # Fetches the file on a network share, returning a Tempfile-like File handle
36
40
  # windows only
37
41
  def fetch
38
- tempfile = Chef::FileContentManagement::Tempfile.new(new_resource).tempfile
39
- Chef::Log.debug("#{new_resource} staging #{@source} to #{tempfile.path}")
40
- FileUtils.cp(@source, tempfile.path)
41
- tempfile.close if tempfile
42
+ begin
43
+ tempfile = Chef::FileContentManagement::Tempfile.new(new_resource).tempfile
44
+ Chef::Log.debug("#{new_resource} staging #{@source} to #{tempfile.path}")
45
+
46
+ with_user_context(new_resource.remote_user, new_resource.remote_password, new_resource.remote_domain) do
47
+ ::File.open(@source, "rb") do |remote_file|
48
+ while data = remote_file.read(TRANSFER_CHUNK_SIZE)
49
+ tempfile.write(data)
50
+ end
51
+ end
52
+ end
53
+ ensure
54
+ tempfile.close if tempfile
55
+ end
42
56
  tempfile
43
57
  end
44
-
45
58
  end
46
59
  end
47
60
  end
@@ -52,17 +52,18 @@ class Chef
52
52
  @plist_size = 0
53
53
  @plist = @new_resource.plist ? @new_resource.plist : find_service_plist
54
54
  @service_label = find_service_label
55
- # LauchAgents should be loaded as the console user.
55
+ # LaunchAgents should be loaded as the console user.
56
56
  @console_user = @plist ? @plist.include?("LaunchAgents") : false
57
57
  @session_type = @new_resource.session_type
58
58
 
59
59
  if @console_user
60
- @console_user = Etc.getlogin
60
+ @console_user = Etc.getpwuid(::File.stat("/dev/console").uid).name
61
61
  Chef::Log.debug("#{new_resource} console_user: '#{@console_user}'")
62
62
  cmd = "su "
63
63
  param = this_version_or_newer?("10.10") ? "" : "-l "
64
+ param = "-l " if this_version_or_newer?("10.12")
64
65
  @base_user_cmd = cmd + param + "#{@console_user} -c"
65
- # Default LauchAgent session should be Aqua
66
+ # Default LaunchAgent session should be Aqua
66
67
  @session_type = "Aqua" if @session_type.nil?
67
68
  end
68
69
 
@@ -0,0 +1,62 @@
1
+ #
2
+ # Author:: Nimisha Sharad (<nimisha.sharad@msystechnologies.com>)
3
+ # Copyright:: Copyright 2008-2017, Chef Software Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require "chef/mixin/windows_env_helper" if Chef::Platform.windows?
20
+ require "chef/mixin/wide_string"
21
+ require "chef/exceptions"
22
+
23
+ class Chef
24
+ class Provider
25
+ class WindowsPath < Chef::Provider
26
+
27
+ include Chef::Mixin::WindowsEnvHelper if Chef::Platform.windows?
28
+
29
+ def load_current_resource
30
+ @current_resource = Chef::Resource::WindowsPath.new(new_resource.name)
31
+ @current_resource.path(new_resource.path)
32
+ @current_resource
33
+ end
34
+
35
+ action :add do
36
+ # The windows Env provider does not correctly expand variables in
37
+ # the PATH environment variable. Ruby expects these to be expanded.
38
+ #
39
+ path = expand_path(new_resource.path)
40
+ converge_by "Adding #{new_resource.path} to path environment variable" do
41
+ declare_resource(:env, "path") do
42
+ action :modify
43
+ delim ::File::PATH_SEPARATOR
44
+ value path.tr("/", '\\')
45
+ end
46
+ end
47
+ end
48
+
49
+ action :remove do
50
+ # The windows Env provider does not correctly expand variables in
51
+ # the PATH environment variable. Ruby expects these to be expanded.
52
+ #
53
+ path = expand_path(new_resource.path)
54
+ declare_resource(:env, "path") do
55
+ action :delete
56
+ delim ::File::PATH_SEPARATOR
57
+ value path.tr("/", '\\')
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -57,7 +57,7 @@ class Chef
57
57
  end
58
58
 
59
59
  action :refresh do
60
- declare_resource(:execute, "zypper refresh #{escaped_repo_name}") do
60
+ declare_resource(:execute, "zypper#{' --gpg-auto-import-keys' if new_resource.gpgautoimportkeys} refresh #{escaped_repo_name}") do
61
61
  only_if "zypper lr #{escaped_repo_name}"
62
62
  end
63
63
  end
@@ -61,6 +61,7 @@ require "chef/provider/whyrun_safe_ruby_block"
61
61
  require "chef/provider/yum_repository"
62
62
  require "chef/provider/windows_task"
63
63
  require "chef/provider/zypper_repository"
64
+ require "chef/provider/windows_path"
64
65
 
65
66
  require "chef/provider/env/windows"
66
67
 
@@ -641,7 +641,11 @@ class Chef
641
641
 
642
642
  all_props = {}
643
643
  self.class.state_properties.map do |p|
644
- all_props[p.name.to_s] = p.sensitive? ? '"*sensitive value suppressed*"' : value_to_text(p.get(self))
644
+ begin
645
+ all_props[p.name.to_s] = p.sensitive? ? '"*sensitive value suppressed*"' : value_to_text(p.get(self))
646
+ rescue Chef::Exceptions::ValidationFailed
647
+ # This space left intentionally blank, the property was probably required or had an invalid default.
648
+ end
645
649
  end
646
650
 
647
651
  ivars = instance_variables.map { |ivar| ivar.to_sym } - HIDDEN_IVARS
@@ -33,7 +33,7 @@ class Chef
33
33
  # whether or not to add the repository as a source repo, too
34
34
  property :deb_src, [TrueClass, FalseClass], default: false
35
35
  property :keyserver, [String, nil, false], default: "keyserver.ubuntu.com", nillable: true, coerce: proc { |x| x ? x : nil }
36
- property :key, [String, nil, false], default: nil, nillable: true, coerce: proc { |x| x ? x : nil }
36
+ property :key, [String, Array, nil, false], default: [], coerce: proc { |x| x ? Array(x) : nil }
37
37
  property :key_proxy, [String, nil, false], default: nil, nillable: true, coerce: proc { |x| x ? x : nil }
38
38
 
39
39
  property :cookbook, [String, nil, false], default: nil, desired_state: false, nillable: true, coerce: proc { |x| x ? x : nil }
@@ -44,6 +44,10 @@ class Chef
44
44
  @network = nil
45
45
  @bootproto = nil
46
46
  @onparent = nil
47
+ @ethtool_opts = nil
48
+ @bonding_opts = nil
49
+ @master = nil
50
+ @slave = nil
47
51
  end
48
52
 
49
53
  def target(arg = nil)
@@ -141,6 +145,38 @@ class Chef
141
145
  :kind_of => String
142
146
  )
143
147
  end
148
+
149
+ def ethtool_opts(arg = nil)
150
+ set_or_return(
151
+ :ethtool_opts,
152
+ arg,
153
+ :kind_of => String
154
+ )
155
+ end
156
+
157
+ def bonding_opts(arg = nil)
158
+ set_or_return(
159
+ :bonding_opts,
160
+ arg,
161
+ :kind_of => String
162
+ )
163
+ end
164
+
165
+ def master(arg = nil)
166
+ set_or_return(
167
+ :master,
168
+ arg,
169
+ :kind_of => String
170
+ )
171
+ end
172
+
173
+ def slave(arg = nil)
174
+ set_or_return(
175
+ :slave,
176
+ arg,
177
+ :kind_of => String
178
+ )
179
+ end
144
180
  end
145
181
 
146
182
  end
@@ -131,6 +131,66 @@ class Chef
131
131
  )
132
132
  end
133
133
 
134
+ property :remote_user, String
135
+
136
+ property :remote_domain, String
137
+
138
+ property :remote_password, String, sensitive: true
139
+
140
+ def after_created
141
+ validate_identity_platform(remote_user, remote_password, remote_domain)
142
+ identity = qualify_user(remote_user, remote_password, remote_domain)
143
+ remote_domain(identity[:domain])
144
+ remote_user(identity[:user])
145
+ end
146
+
147
+ def validate_identity_platform(specified_user, password = nil, specified_domain = nil)
148
+ if node[:platform_family] == "windows"
149
+ if specified_user && password.nil?
150
+ raise ArgumentError, "A value for `remote_password` must be specified when a value for `user` is specified on the Windows platform"
151
+ end
152
+ end
153
+ end
154
+
155
+ def qualify_user(specified_user, password = nil, specified_domain = nil)
156
+ domain = specified_domain
157
+ user = specified_user
158
+
159
+ if specified_user.nil? && ! specified_domain.nil?
160
+ raise ArgumentError, "The domain `#{specified_domain}` was specified, but no user name was given"
161
+ end
162
+
163
+ # if domain is provided in both username and domain
164
+ if specified_user && ((specified_user.include? '\\') || (specified_user.include? "@")) && specified_domain
165
+ raise ArgumentError, "The domain is provided twice. Username: `#{specified_user}`, Domain: `#{specified_domain}`. Please specify domain only once."
166
+ end
167
+
168
+ if ! specified_user.nil? && specified_domain.nil?
169
+ # Splitting username of format: Domain\Username
170
+ domain_and_user = user.split('\\')
171
+
172
+ if domain_and_user.length == 2
173
+ domain = domain_and_user[0]
174
+ user = domain_and_user[1]
175
+ elsif domain_and_user.length == 1
176
+ # Splitting username of format: Username@Domain
177
+ domain_and_user = user.split("@")
178
+ if domain_and_user.length == 2
179
+ domain = domain_and_user[1]
180
+ user = domain_and_user[0]
181
+ elsif domain_and_user.length != 1
182
+ raise ArgumentError, "The specified user name `#{user}` is not a syntactically valid user name"
183
+ end
184
+ end
185
+ end
186
+
187
+ if ( password || domain ) && user.nil?
188
+ raise ArgumentError, "A value for `password` or `domain` was specified without specification of a value for `user`"
189
+ end
190
+
191
+ { domain: domain, user: user }
192
+ end
193
+
134
194
  private
135
195
 
136
196
  include Chef::Mixin::Uris
@@ -0,0 +1,41 @@
1
+ #
2
+ # Author:: Nimisha Sharad (<nimisha.sharad@msystechnologies.com>)
3
+ # Copyright:: Copyright 2008-2017, Chef Software Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require "chef/resource"
20
+
21
+ class Chef
22
+ class Resource
23
+ class WindowsPath < Chef::Resource
24
+
25
+ provides :windows_path, os: "windows"
26
+
27
+ allowed_actions :add, :remove
28
+ default_action :add
29
+
30
+ def initialize(name, run_context = nil)
31
+ super
32
+ @resource_name = :windows_path
33
+ @path = name
34
+ @provider = Chef::Provider::WindowsPath
35
+ @action = :add
36
+ end
37
+
38
+ property :path, String, name_property: true
39
+ end
40
+ end
41
+ end
@@ -39,6 +39,7 @@ class Chef
39
39
  property :mode, default: "0644"
40
40
  property :refresh_cache, [true, false], default: true
41
41
  property :source, String, regex: /.*/
42
+ property :gpgautoimportkeys, [true, false], default: true
42
43
 
43
44
  default_action :create
44
45
  allowed_actions :create, :remove, :add, :refresh
@@ -101,3 +101,4 @@ require "chef/resource/cab_package"
101
101
  require "chef/resource/powershell_package"
102
102
  require "chef/resource/msu_package"
103
103
  require "chef/resource/windows_task"
104
+ require "chef/resource/windows_path"
@@ -138,6 +138,7 @@ module Shell
138
138
  def self.session
139
139
  unless client_type.instance.node_built?
140
140
  puts "Session type: #{client_type.session_type}"
141
+ client_type.instance.json_configuration = @json_attribs
141
142
  client_type.instance.reset!
142
143
  end
143
144
  client_type.instance
@@ -38,7 +38,7 @@ module Shell
38
38
  @session_type
39
39
  end
40
40
 
41
- attr_accessor :node, :compile, :recipe, :run_context
41
+ attr_accessor :node, :compile, :recipe, :run_context, :json_configuration
42
42
  attr_reader :node_attributes, :client
43
43
  def initialize
44
44
  @node_built = false
@@ -151,7 +151,7 @@ module Shell
151
151
 
152
152
  def rebuild_node
153
153
  Chef::Config[:solo_legacy_mode] = true
154
- @client = Chef::Client.new(nil, Chef::Config[:shell_config])
154
+ @client = Chef::Client.new(json_configuration, Chef::Config[:shell_config])
155
155
  @client.run_ohai
156
156
  @client.load_node
157
157
  @client.build_node
@@ -183,7 +183,7 @@ module Shell
183
183
  def rebuild_node
184
184
  # Tell the client we're chef solo so it won't try to contact the server
185
185
  Chef::Config[:solo_legacy_mode] = true
186
- @client = Chef::Client.new(nil, Chef::Config[:shell_config])
186
+ @client = Chef::Client.new(json_configuration, Chef::Config[:shell_config])
187
187
  @client.run_ohai
188
188
  @client.load_node
189
189
  @client.build_node
@@ -218,7 +218,7 @@ module Shell
218
218
  def rebuild_node
219
219
  # Make sure the client knows this is not chef solo
220
220
  Chef::Config[:solo_legacy_mode] = false
221
- @client = Chef::Client.new(nil, Chef::Config[:shell_config])
221
+ @client = Chef::Client.new(json_configuration, Chef::Config[:shell_config])
222
222
  @client.run_ohai
223
223
  @client.register
224
224
  @client.load_node
@@ -0,0 +1,126 @@
1
+ #
2
+ # Author:: Adam Edwards (<adamed@chef.io>)
3
+ #
4
+ # Copyright:: Copyright (c) 2015 Chef Software, Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require "chef/win32/api/security" if Chef::Platform.windows?
20
+ require "chef/mixin/wide_string"
21
+
22
+ class Chef
23
+ class Util
24
+ class Windows
25
+ class LogonSession
26
+ include Chef::Mixin::WideString
27
+
28
+ def initialize(username, password, domain = nil)
29
+ if username.nil? || password.nil?
30
+ raise ArgumentError, "The logon session must be initialize with non-nil user name and password parameters"
31
+ end
32
+
33
+ @original_username = username
34
+ @original_password = password
35
+ @original_domain = domain
36
+ @token = FFI::Buffer.new(:pointer)
37
+ @session_opened = false
38
+ @impersonating = false
39
+ end
40
+
41
+ def open
42
+ if session_opened
43
+ raise "Attempted to open a logon session that was already open."
44
+ end
45
+
46
+ username = wstring(original_username)
47
+ password = wstring(original_password)
48
+ domain = wstring(original_domain)
49
+
50
+ status = Chef::ReservedNames::Win32::API::Security.LogonUserW(username, domain, password, Chef::ReservedNames::Win32::API::Security::LOGON32_LOGON_NEW_CREDENTIALS, Chef::ReservedNames::Win32::API::Security::LOGON32_PROVIDER_DEFAULT, token)
51
+
52
+ if !status
53
+ last_error = FFI::LastError.error
54
+ raise Chef::Exceptions::Win32APIError, "Logon for user `#{original_username}` failed with Win32 status #{last_error}."
55
+ end
56
+
57
+ @session_opened = true
58
+ end
59
+
60
+ def close
61
+ validate_session_open!
62
+
63
+ if impersonating
64
+ restore_user_context
65
+ end
66
+
67
+ Chef::ReservedNames::Win32::API::System.CloseHandle(token.read_ulong)
68
+ @token = nil
69
+ @session_opened = false
70
+ end
71
+
72
+ def set_user_context
73
+ validate_session_open!
74
+
75
+ if ! session_opened
76
+ raise "Attempted to set the user context before opening a session."
77
+ end
78
+
79
+ if impersonating
80
+ raise "Attempt to set the user context when the user context is already set."
81
+ end
82
+
83
+ status = Chef::ReservedNames::Win32::API::Security.ImpersonateLoggedOnUser(token.read_ulong)
84
+
85
+ if !status
86
+ last_error = FFI::LastError.error
87
+ raise Chef::Exceptions::Win32APIError, "Attempt to impersonate user `#{original_username}` failed with Win32 status #{last_error}."
88
+ end
89
+
90
+ @impersonating = true
91
+ end
92
+
93
+ def restore_user_context
94
+ validate_session_open!
95
+
96
+ if impersonating
97
+ status = Chef::ReservedNames::Win32::API::Security.RevertToSelf
98
+
99
+ if !status
100
+ last_error = FFI::LastError.error
101
+ raise Chef::Exceptions::Win32APIError, "Unable to restore user context with Win32 status #{last_error}."
102
+ end
103
+ end
104
+
105
+ @impersonating = false
106
+ end
107
+
108
+ protected
109
+
110
+ attr_reader :original_username
111
+ attr_reader :original_password
112
+ attr_reader :original_domain
113
+
114
+ attr_reader :token
115
+ attr_reader :session_opened
116
+ attr_reader :impersonating
117
+
118
+ def validate_session_open!
119
+ if ! session_opened
120
+ raise "Attempted to set the user context before opening a session."
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end