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.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/VERSION +1 -1
- data/lib/.DS_Store +0 -0
- data/lib/chef/.DS_Store +0 -0
- data/lib/chef/knife/core/ui.rb +1 -1
- data/lib/chef/mash.rb +6 -0
- data/lib/chef/mixin/deep_merge.rb +1 -1
- data/lib/chef/mixin/user_context.rb +52 -0
- data/lib/chef/node/attribute.rb +80 -14
- data/lib/chef/node/immutable_collections.rb +16 -19
- data/lib/chef/provider/apt_repository.rb +12 -10
- data/lib/chef/provider/git.rb +20 -3
- data/lib/chef/provider/ifconfig/redhat.rb +4 -0
- data/lib/chef/provider/launchd.rb +20 -0
- data/lib/chef/provider/package/dnf.rb +3 -1
- data/lib/chef/provider/remote_file.rb +19 -0
- data/lib/chef/provider/remote_file/fetcher.rb +3 -0
- data/lib/chef/provider/remote_file/network_file.rb +18 -5
- data/lib/chef/provider/service/macosx.rb +4 -3
- data/lib/chef/provider/windows_path.rb +62 -0
- data/lib/chef/provider/zypper_repository.rb +1 -1
- data/lib/chef/providers.rb +1 -0
- data/lib/chef/resource.rb +5 -1
- data/lib/chef/resource/apt_repository.rb +1 -1
- data/lib/chef/resource/ifconfig.rb +36 -0
- data/lib/chef/resource/remote_file.rb +60 -0
- data/lib/chef/resource/windows_path.rb +41 -0
- data/lib/chef/resource/zypper_repository.rb +1 -0
- data/lib/chef/resources.rb +1 -0
- data/lib/chef/shell.rb +1 -0
- data/lib/chef/shell/shell_session.rb +4 -4
- data/lib/chef/util/windows/logon_session.rb +126 -0
- data/lib/chef/version.rb +4 -3
- data/lib/chef/win32/api/security.rb +2 -0
- data/spec/.DS_Store +0 -0
- data/spec/data/nodes/Timothys-MacBook-Pro.local.json +3 -0
- data/spec/functional/.DS_Store +0 -0
- data/spec/functional/mixin/user_context_spec.rb +117 -0
- data/spec/functional/resource/remote_file_spec.rb +171 -0
- data/spec/functional/resource/windows_path_spec.rb +64 -0
- data/spec/support/.DS_Store +0 -0
- data/spec/unit/.DS_Store +0 -0
- data/spec/unit/knife/client_delete_spec.rb +1 -1
- data/spec/unit/mixin/user_context_spec.rb +109 -0
- data/spec/unit/node/immutable_collections_spec.rb +12 -4
- data/spec/unit/node_spec.rb +7 -0
- data/spec/unit/provider/git_spec.rb +55 -0
- data/spec/unit/provider/ifconfig/redhat_spec.rb +8 -0
- data/spec/unit/provider/remote_file/fetcher_spec.rb +1 -0
- data/spec/unit/provider/remote_file/network_file_spec.rb +7 -2
- data/spec/unit/provider/service/macosx_spec.rb +4 -1
- data/spec/unit/provider/windows_path_spec.rb +65 -0
- data/spec/unit/resource/windows_path_spec.rb +38 -0
- data/spec/unit/resource_spec.rb +8 -0
- data/spec/unit/shell/shell_session_spec.rb +82 -58
- data/spec/unit/util/windows/logon_session_spec.rb +284 -0
- data/tasks/maintainers.rb +3 -3
- 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{
|
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
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
#
|
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.
|
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
|
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
|
data/lib/chef/providers.rb
CHANGED
data/lib/chef/resource.rb
CHANGED
@@ -641,7 +641,11 @@ class Chef
|
|
641
641
|
|
642
642
|
all_props = {}
|
643
643
|
self.class.state_properties.map do |p|
|
644
|
-
|
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:
|
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
|
data/lib/chef/resources.rb
CHANGED
data/lib/chef/shell.rb
CHANGED
@@ -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(
|
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(
|
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(
|
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
|