chef 16.14.1 → 16.17.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/lib/chef/action_collection.rb +1 -1
  3. data/lib/chef/application.rb +1 -1
  4. data/lib/chef/cookbook_version.rb +26 -4
  5. data/lib/chef/data_collector/run_end_message.rb +2 -2
  6. data/lib/chef/deprecated.rb +14 -4
  7. data/lib/chef/exceptions.rb +3 -0
  8. data/lib/chef/formatters/error_mapper.rb +2 -2
  9. data/lib/chef/http.rb +5 -5
  10. data/lib/chef/knife/bootstrap.rb +1 -1
  11. data/lib/chef/node.rb +20 -19
  12. data/lib/chef/policy_builder/policyfile.rb +5 -0
  13. data/lib/chef/provider/group/dscl.rb +1 -1
  14. data/lib/chef/provider/package/powershell.rb +5 -0
  15. data/lib/chef/provider/template/content.rb +1 -1
  16. data/lib/chef/resource/chef_client_trusted_certificate.rb +1 -0
  17. data/lib/chef/resource/homebrew_cask.rb +13 -7
  18. data/lib/chef/resource/mount.rb +1 -1
  19. data/lib/chef/resource/rhsm_subscription.rb +5 -5
  20. data/lib/chef/resource/support/client.erb +6 -0
  21. data/lib/chef/resource/systemd_unit.rb +1 -1
  22. data/lib/chef/resource/user_ulimit.rb +1 -0
  23. data/lib/chef/resource/windows_security_policy.rb +55 -39
  24. data/lib/chef/resource/windows_uac.rb +3 -1
  25. data/lib/chef/resource/windows_user_privilege.rb +1 -1
  26. data/lib/chef/resource.rb +1 -1
  27. data/lib/chef/resource_reporter.rb +1 -1
  28. data/lib/chef/shell/ext.rb +3 -3
  29. data/lib/chef/version.rb +1 -1
  30. data/lib/chef/win32/api.rb +9 -2
  31. data/lib/chef/win32/version.rb +2 -1
  32. data/spec/functional/resource/group_spec.rb +5 -1
  33. data/spec/functional/resource/link_spec.rb +8 -0
  34. data/spec/integration/knife/delete_spec.rb +1 -1
  35. data/spec/integration/knife/download_spec.rb +2 -2
  36. data/spec/integration/knife/upload_spec.rb +5 -6
  37. data/spec/unit/cookbook_version_spec.rb +52 -0
  38. data/spec/unit/data_collector_spec.rb +71 -2
  39. data/spec/unit/policy_builder/policyfile_spec.rb +11 -1
  40. data/spec/unit/provider/package/powershell_spec.rb +74 -12
  41. data/spec/unit/resource/chef_client_trusted_certificate_spec.rb +14 -0
  42. data/spec/unit/resource/homebrew_cask_spec.rb +29 -11
  43. data/spec/unit/resource/mount_spec.rb +10 -0
  44. data/spec/unit/resource/rhsm_subscription_spec.rb +50 -3
  45. data/spec/unit/resource/systemd_unit_spec.rb +1 -1
  46. data/spec/unit/resource/user_ulimit_spec.rb +14 -1
  47. data/spec/unit/resource_spec.rb +5 -0
  48. metadata +6 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c9b7fb70681334021fb8862c446ed789da0782c21a3eecaf332dbe2d6b140fa
4
- data.tar.gz: 2324b707db73fa2b895253c881911713e59b72905055590dcef5bcf63e1105db
3
+ metadata.gz: c600cebfc79b7b124f1017921af9c5044322ec47d8f06580bac479eb7aa908e2
4
+ data.tar.gz: 889d51f238676329b075bf34881a937d334bab0e920e9dc8bb3ea1b3693dbbc3
5
5
  SHA512:
6
- metadata.gz: bf4e6692007a79c0ee84b88a10bd9f9a31df1458cbd00ae99922cca8a4c880a5739da83d103e44a263b55f035e8a7a822de84355bdf1124a4048b82f79649ae9
7
- data.tar.gz: 4b296a37c1a5444c3100c31bb61c92e27c799b0082d8d8da3925eed2c641aa5faeea4c76127b2ec8c8c09ffacf1e610891a87138ce53e675d4c81fc1f1aaa353
6
+ metadata.gz: 84a4cf060f25d26486191be0010b1e9a8ec31ea180531ef94afe00a36038b36f0e26de96cba33da2f78f6fefb2ae83fc2fceaf2b91f495c895f92245f7d4620f
7
+ data.tar.gz: c6f757ad7b6db16c8ce3b344f00006324f52aa90821e64b4a6f6c078ba97b87a4a1eb16b41380a5910a14fe116637210dee73298f2e605e77c20cce84cd4b20d
@@ -128,7 +128,7 @@ class Chef
128
128
  #
129
129
  def cookbook_compilation_start(run_context)
130
130
  run_context.action_collection = self
131
- # fire the action_colleciton_registration hook after cookbook_compilation_start -- last chance for consumers to register
131
+ # fire the action_collection_registration hook after cookbook_compilation_start -- last chance for consumers to register
132
132
  run_context.events.enqueue(:action_collection_registration, self)
133
133
  @run_context = run_context
134
134
  end
@@ -310,7 +310,7 @@ class Chef
310
310
  logger.info "Forking #{ChefUtils::Dist::Infra::PRODUCT} instance to converge..."
311
311
  pid = fork do
312
312
  # Want to allow forked processes to finish converging when
313
- # TERM singal is received (exit gracefully)
313
+ # TERM signal is received (exit gracefully)
314
314
  trap("TERM") do
315
315
  logger.debug("SIGTERM received during converge," +
316
316
  " finishing converge to exit normally (send SIGINT to terminate immediately)")
@@ -138,11 +138,14 @@ class Chef
138
138
  end
139
139
 
140
140
  def recipe_yml_filenames_by_name
141
- @recipe_ym_filenames_by_name ||= begin
141
+ @recipe_yml_filenames_by_name ||= begin
142
142
  name_map = yml_filenames_by_name(files_for("recipes"))
143
- root_alias = cookbook_manifest.root_files.find { |record| record[:name] == "root_files/recipe.yml" }
143
+ root_alias = cookbook_manifest.root_files.find { |record|
144
+ record[:name] == "root_files/recipe.yml" ||
145
+ record[:name] == "root_files/recipe.yaml"
146
+ }
144
147
  if root_alias
145
- Chef::Log.error("Cookbook #{name} contains both recipe.yml and and recipes/default.yml, ignoring recipes/default.yml") if name_map["default"]
148
+ Chef::Log.error("Cookbook #{name} contains both recipe.yml and recipes/default.yml, ignoring recipes/default.yml") if name_map["default"]
146
149
  name_map["default"] = root_alias[:full_path]
147
150
  end
148
151
  name_map
@@ -582,8 +585,27 @@ class Chef
582
585
  records.select { |record| record[:name] =~ /\.rb$/ }.inject({}) { |memo, record| memo[File.basename(record[:name], ".rb")] = record[:full_path]; memo }
583
586
  end
584
587
 
588
+ # Filters YAML files from the superset of provided files.
589
+ # Checks for duplicate basenames with differing extensions (eg yaml v yml)
590
+ # and raises error if any are detected.
591
+ # This prevents us from arbitrarily the ".yaml" or ".yml" version when both are present,
592
+ # because we don't know which is correct.
593
+ # This method runs in O(n^2) where N = number of yml files present. This number should be consistently
594
+ # low enough that there's no noticeable perf impact.
585
595
  def yml_filenames_by_name(records)
586
- records.select { |record| record[:name] =~ /\.yml$/ }.inject({}) { |memo, record| memo[File.basename(record[:name], ".yml")] = record[:full_path]; memo }
596
+ yml_files = records.select { |record| record[:name] =~ /\.(y[a]?ml)$/ }
597
+ result = yml_files.inject({}) do |acc, record|
598
+ filename = record[:name]
599
+ base_dup_name = File.join(File.dirname(filename), File.basename(filename, File.extname(filename)))
600
+ yml_files.each do |other|
601
+ if other[:name] =~ /#{(File.extname(filename) == ".yml") ? "#{base_dup_name}.yaml" : "#{base_dup_name}.yml"}$/
602
+ raise Chef::Exceptions::AmbiguousYAMLFile.new("Cookbook #{name}@#{version} contains ambiguous files: #{filename} and #{other[:name]}. Please update the cookbook to remove the incorrect file.")
603
+ end
604
+ end
605
+ acc[File.basename(record[:name], File.extname(record[:name]))] = record[:full_path]
606
+ acc
607
+ end
608
+ result
587
609
  end
588
610
 
589
611
  def file_vendor
@@ -51,7 +51,7 @@ class Chef
51
51
  "id" => run_status&.run_id,
52
52
  "message_version" => "1.1.0",
53
53
  "message_type" => "run_converge",
54
- "node" => node || {},
54
+ "node" => node&.data_for_save || {},
55
55
  "node_name" => node&.name || data_collector.node_name,
56
56
  "organization_name" => organization,
57
57
  "resources" => all_action_records(action_collection),
@@ -128,7 +128,7 @@ class Chef
128
128
 
129
129
  if new_resource.cookbook_name
130
130
  hash["cookbook_name"] = new_resource.cookbook_name
131
- hash["cookbook_version"] = new_resource.cookbook_version.version
131
+ hash["cookbook_version"] = new_resource.cookbook_version&.version
132
132
  hash["recipe_name"] = new_resource.recipe_name
133
133
  end
134
134
 
@@ -79,10 +79,12 @@ class Chef
79
79
  return true if location =~ /^(.*?):(\d+):in/ && begin
80
80
  # Don't buffer the whole file in memory, so read it one line at a time.
81
81
  line_no = $2.to_i
82
- location_file = ::File.open($1)
83
- (line_no - 1).times { location_file.readline } # Read all the lines we don't care about.
84
- relevant_line = location_file.readline
85
- relevant_line.match?(/#.*chef:silence_deprecation($|[^:]|:#{self.class.deprecation_key})/)
82
+ if File.exist?($1) # some stacktraces come from `eval` and not a file
83
+ location_file = ::File.open($1)
84
+ (line_no - 1).times { location_file.readline } # Read all the lines we don't care about.
85
+ relevant_line = location_file.readline
86
+ relevant_line.match?(/#.*chef:silence_deprecation($|[^:]|:#{self.class.deprecation_key})/)
87
+ end
86
88
  end
87
89
 
88
90
  false
@@ -249,6 +251,14 @@ class Chef
249
251
  target 32
250
252
  end
251
253
 
254
+ class PolicyfileCompatMode < Base
255
+ target 35
256
+ end
257
+
258
+ class AttributeWhitelistConfiguration < Base
259
+ target 34
260
+ end
261
+
252
262
  class Generic < Base
253
263
  def url
254
264
  "https://docs.chef.io/chef_deprecations_client/"
@@ -174,6 +174,9 @@ class Chef
174
174
  class CannotDetermineWindowsInstallerType < Package; end
175
175
  class NoWindowsPackageSource < Package; end
176
176
 
177
+ # for example, if both recipes/default.yml, recipes/default.yaml are present
178
+ class AmbiguousYAMLFile < RuntimeError; end
179
+
177
180
  # Can not create staging file during file deployment
178
181
  class FileContentStagingError < RuntimeError
179
182
  def initialize(errors)
@@ -27,7 +27,7 @@ class Chef
27
27
  # Failed to register this client with the server.
28
28
  def self.registration_failed(node_name, exception, config)
29
29
  error_inspector = ErrorInspectors::RegistrationErrorInspector.new(node_name, exception, config)
30
- headline = "Chef encountered an error attempting to create the client \"#{node_name}\""
30
+ headline = "Chef Infra Client encountered an error attempting to create the client \"#{node_name}\""
31
31
  description = ErrorDescription.new(headline)
32
32
  error_inspector.add_explanation(description)
33
33
  description
@@ -35,7 +35,7 @@ class Chef
35
35
 
36
36
  def self.node_load_failed(node_name, exception, config)
37
37
  error_inspector = ErrorInspectors::NodeLoadErrorInspector.new(node_name, exception, config)
38
- headline = "Chef encountered an error attempting to load the node data for \"#{node_name}\""
38
+ headline = "Chef Infra Client encountered an error attempting to load the node data for \"#{node_name}\""
39
39
  description = ErrorDescription.new(headline)
40
40
  error_inspector.add_explanation(description)
41
41
  description
data/lib/chef/http.rb CHANGED
@@ -423,7 +423,7 @@ class Chef
423
423
  if response.is_a?(Net::HTTPServerError) && !Chef::Config.local_mode
424
424
  if http_retry_count - http_attempts >= 0
425
425
  sleep_time = 1 + (2**http_attempts) + rand(2**http_attempts)
426
- Chef::Log.error("Server returned error #{response.code} for #{url}, retrying #{http_attempts}/#{http_retry_count} in #{sleep_time}s")
426
+ Chef::Log.warn("Server returned error #{response.code} for #{url}, retrying #{http_attempts}/#{http_retry_count} in #{sleep_time}s") # Updated from error to warn
427
427
  sleep(sleep_time)
428
428
  redo
429
429
  end
@@ -432,7 +432,7 @@ class Chef
432
432
  end
433
433
  rescue SocketError, Errno::ETIMEDOUT, Errno::ECONNRESET => e
434
434
  if http_retry_count - http_attempts >= 0
435
- Chef::Log.error("Error connecting to #{url}, retry #{http_attempts}/#{http_retry_count}")
435
+ Chef::Log.warn("Error connecting to #{url}, retry #{http_attempts}/#{http_retry_count}") # Updated from error to warn
436
436
  sleep(http_retry_delay)
437
437
  retry
438
438
  end
@@ -440,21 +440,21 @@ class Chef
440
440
  raise e
441
441
  rescue Errno::ECONNREFUSED
442
442
  if http_retry_count - http_attempts >= 0
443
- Chef::Log.error("Connection refused connecting to #{url}, retry #{http_attempts}/#{http_retry_count}")
443
+ Chef::Log.warn("Connection refused connecting to #{url}, retry #{http_attempts}/#{http_retry_count}") # Updated from error to warn
444
444
  sleep(http_retry_delay)
445
445
  retry
446
446
  end
447
447
  raise Errno::ECONNREFUSED, "Connection refused connecting to #{url}, giving up"
448
448
  rescue Timeout::Error
449
449
  if http_retry_count - http_attempts >= 0
450
- Chef::Log.error("Timeout connecting to #{url}, retry #{http_attempts}/#{http_retry_count}")
450
+ Chef::Log.warn("Timeout connecting to #{url}, retry #{http_attempts}/#{http_retry_count}") # Updated from error to warn
451
451
  sleep(http_retry_delay)
452
452
  retry
453
453
  end
454
454
  raise Timeout::Error, "Timeout connecting to #{url}, giving up"
455
455
  rescue OpenSSL::SSL::SSLError => e
456
456
  if (http_retry_count - http_attempts >= 0) && !e.message.include?("certificate verify failed")
457
- Chef::Log.error("SSL Error connecting to #{url}, retry #{http_attempts}/#{http_retry_count}")
457
+ Chef::Log.warn("SSL Error connecting to #{url}, retry #{http_attempts}/#{http_retry_count}") # Updated from error to warn
458
458
  sleep(http_retry_delay)
459
459
  retry
460
460
  end
@@ -473,7 +473,7 @@ class Chef
473
473
  end
474
474
 
475
475
  # The server_name is the DNS or IP we are going to connect to, it is not necessarily
476
- # the node name, the fqdn, or the hostname of the server. This is a public API hook
476
+ # the node name, the fqdn, or the hostname of the server. This is a public API hook
477
477
  # which knife plugins use or inherit and override.
478
478
  #
479
479
  # @return [String] The DNS or IP that bootstrap will connect to
data/lib/chef/node.rb CHANGED
@@ -687,6 +687,25 @@ class Chef
687
687
  name <=> other.name
688
688
  end
689
689
 
690
+ # Returns hash of node data with attributes based on whitelist/blacklist rules.
691
+ def data_for_save
692
+ data = for_json
693
+ %w{automatic default normal override}.each do |level|
694
+ allowlist = allowlist_or_whitelist_config(level)
695
+ unless allowlist.nil? # nil => save everything
696
+ logger.info("Allowing #{level} node attributes for save.")
697
+ data[level] = Chef::AttributeAllowlist.filter(data[level], allowlist)
698
+ end
699
+
700
+ blocklist = blocklist_or_blacklist_config(level)
701
+ unless blocklist.nil? # nil => remove nothing
702
+ logger.info("Blocking #{level} node attributes for save")
703
+ data[level] = Chef::AttributeBlocklist.filter(data[level], blocklist)
704
+ end
705
+ end
706
+ data
707
+ end
708
+
690
709
  private
691
710
 
692
711
  def save_without_policyfile_attrs
@@ -712,7 +731,7 @@ class Chef
712
731
  # @param [String] level the attribute level
713
732
  def allowlist_or_whitelist_config(level)
714
733
  if Chef::Config["#{level}_attribute_whitelist".to_sym]
715
- Chef.deprecated(:attribute_blacklist_configuration, "Attribute whitelist configurations have been deprecated. Use the allowed_LEVEL_attribute configs instead")
734
+ Chef.deprecated(:attribute_whitelist_configuration, "Attribute whitelist configurations have been deprecated. Use the allowed_LEVEL_attribute configs instead")
716
735
  Chef::Config["#{level}_attribute_whitelist".to_sym]
717
736
  else
718
737
  Chef::Config["allowed_#{level}_attributes".to_sym]
@@ -732,24 +751,6 @@ class Chef
732
751
  end
733
752
  end
734
753
 
735
- def data_for_save
736
- data = for_json
737
- %w{automatic default normal override}.each do |level|
738
- allowlist = allowlist_or_whitelist_config(level)
739
- unless allowlist.nil? # nil => save everything
740
- logger.info("Allowing #{level} node attributes for save.")
741
- data[level] = Chef::AttributeAllowlist.filter(data[level], allowlist)
742
- end
743
-
744
- blocklist = blocklist_or_blacklist_config(level)
745
- unless blocklist.nil? # nil => remove nothing
746
- logger.info("Blocking #{level} node attributes for save")
747
- data[level] = Chef::AttributeBlocklist.filter(data[level], blocklist)
748
- end
749
- end
750
- data
751
- end
752
-
753
754
  # Returns a UUID that uniquely identifies this node for reporting reasons.
754
755
  #
755
756
  # The node is read in from disk if it exists, or it's generated if it does
@@ -148,6 +148,11 @@ class Chef
148
148
  # consume_external_attrs may add items to the run_list. Save the
149
149
  # expanded run_list, which we will pass to the server later to
150
150
  # determine which versions of cookbooks to use.
151
+
152
+ unless Chef::Config[:policy_document_native_api]
153
+ Chef.deprecated(:policyfile_compat_mode, "The chef-server 11 policyfile compat mode is deprecated, please set policy_document_native_api to true in your config")
154
+ end
155
+
151
156
  node.reset_defaults_and_overrides
152
157
 
153
158
  node.consume_external_attrs(ohai_data, json_attribs)
@@ -158,7 +158,7 @@ class Chef
158
158
  if new_resource.group_name && (current_resource.group_name != new_resource.group_name)
159
159
  dscl_create_group
160
160
  end
161
- if new_resource.gid && (current_resource.gid != new_resource.gid)
161
+ if new_resource.gid && (current_resource.gid != new_resource.gid.to_s)
162
162
  set_gid
163
163
  end
164
164
  if new_resource.members || new_resource.excluded_members
@@ -124,6 +124,11 @@ class Chef
124
124
  command.push("-RequiredVersion #{version}") if version
125
125
  command.push("-Source #{new_resource.source}") if new_resource.source && cmdlet_name =~ Regexp.union(/Install-Package/, /Find-Package/)
126
126
  command.push("-SkipPublisherCheck") if new_resource.skip_publisher_check && cmdlet_name !~ /Find-Package/
127
+ if new_resource.options && cmdlet_name !~ Regexp.union(/Get-Package/, /Find-Package/)
128
+ new_resource.options.each do |arg|
129
+ command.push(arg) unless command.include?(arg)
130
+ end
131
+ end
127
132
  command.push(").Version")
128
133
  command.join(" ")
129
134
  end
@@ -65,7 +65,7 @@ class Chef
65
65
  context[:template_finder] = template_finder
66
66
 
67
67
  # helper variables
68
- context[:cookbook_name] = new_resource.cookbook_name unless context.keys.include?(:coookbook_name)
68
+ context[:cookbook_name] = new_resource.cookbook_name unless context.keys.include?(:cookbook_name)
69
69
  context[:recipe_name] = new_resource.recipe_name unless context.keys.include?(:recipe_name)
70
70
  context[:recipe_line_string] = new_resource.source_line unless context.keys.include?(:recipe_line_string)
71
71
  context[:recipe_path] = new_resource.source_line_file unless context.keys.include?(:recipe_path)
@@ -75,6 +75,7 @@ class Chef
75
75
  file cert_path do
76
76
  content new_resource.certificate
77
77
  mode "0640"
78
+ sensitive new_resource.sensitive
78
79
  end
79
80
  end
80
81
 
@@ -34,7 +34,7 @@ class Chef
34
34
 
35
35
  property :cask_name, String,
36
36
  description: "An optional property to set the cask name if it differs from the resource block's name.",
37
- regex: %r{^[\w/-]+$},
37
+ regex: %r{^[\w/\-@]+$},
38
38
  validation_message: "The provided Homebrew cask name is not valid. Cask names can contain alphanumeric characters, _, -, or / only!",
39
39
  name_property: true
40
40
 
@@ -54,9 +54,12 @@ class Chef
54
54
  default: lazy { find_homebrew_username }
55
55
 
56
56
  action :install do
57
- description "Install an application packaged as a Homebrew cask."
58
-
59
- homebrew_tap "homebrew/cask" if new_resource.install_cask
57
+ if new_resource.install_cask
58
+ homebrew_tap "homebrew/cask" do
59
+ homebrew_path new_resource.homebrew_path
60
+ owner new_resource.owner
61
+ end
62
+ end
60
63
 
61
64
  unless casked?
62
65
  converge_by("install cask #{new_resource.cask_name} #{new_resource.options}") do
@@ -69,9 +72,12 @@ class Chef
69
72
  end
70
73
 
71
74
  action :remove do
72
- description "Remove an application packaged as a Homebrew cask."
73
-
74
- homebrew_tap "homebrew/cask" if new_resource.install_cask
75
+ if new_resource.install_cask
76
+ homebrew_tap "homebrew/cask" do
77
+ homebrew_path new_resource.homebrew_path
78
+ owner new_resource.owner
79
+ end
80
+ end
75
81
 
76
82
  if casked?
77
83
  converge_by("uninstall cask #{new_resource.cask_name}") do
@@ -41,7 +41,7 @@ class Chef
41
41
  sensitive: true
42
42
 
43
43
  property :mount_point, String, name_property: true,
44
- coerce: proc { |arg| arg.chomp("/") }, # Removed "/" from the end of str, because it was causing idempotency issue.
44
+ coerce: proc { |arg| (arg == "/" || arg.match?(":/$")) ? arg : arg.chomp("/") }, # Removed "/" from the end of str, because it was causing idempotency issue.
45
45
  description: "The directory (or path) in which the device is to be mounted. Defaults to the name of the resource block if not provided."
46
46
 
47
47
  property :device, String, identity: true,
@@ -34,11 +34,11 @@ class Chef
34
34
  action :attach do
35
35
  description "Attach the node to a subscription pool."
36
36
 
37
- execute "Attach subscription pool #{new_resource.pool_id}" do
38
- command "subscription-manager attach --pool=#{new_resource.pool_id}"
39
- default_env true
40
- action :run
41
- not_if { subscription_attached?(new_resource.pool_id) }
37
+ unless subscription_attached?(new_resource.pool_id)
38
+ converge_by("attach subscription pool #{new_resource.pool_id}") do
39
+ shell_out!("subscription-manager attach --pool=#{new_resource.pool_id}")
40
+ build_resource(:package, "rhsm_subscription-#{new_resource.pool_id}-flush_cache").run_action(:flush_cache)
41
+ end
42
42
  end
43
43
  end
44
44
 
@@ -22,6 +22,12 @@
22
22
  <% next if instance_variable_get(prop).nil? || instance_variable_get(prop).empty? -%>
23
23
  <%=prop.delete_prefix("@") %> <%= instance_variable_get(prop).inspect %>
24
24
  <% end -%>
25
+ <%# ohai_disabled_plugins and ohai_optional_plugins properties don't match the config value perfectly-%>
26
+ <% %w(@ohai_disabled_plugins
27
+ @ohai_optional_plugins).each do |prop| -%>
28
+ <% next if instance_variable_get(prop).nil? || instance_variable_get(prop).empty? -%>
29
+ <%=prop.gsub("@ohai_", "ohai.") %> <%= instance_variable_get(prop).inspect %>
30
+ <% end -%>
25
31
  <%# log_location is special due to STDOUT/STDERR from String -> IO Object -%>
26
32
  <% unless @log_location.nil? %>
27
33
  <% if @log_location.is_a?(String) && %w(STDOUT STDERR).include?(@log_location) -%>
@@ -113,7 +113,7 @@ class Chef
113
113
  when Hash
114
114
  IniParse.gen do |doc|
115
115
  content.each_pair do |sect, opts|
116
- doc.section(sect) do |section|
116
+ doc.section(sect, { option_sep: "=" }) do |section|
117
117
  opts.each_pair do |opt, val|
118
118
  [val].flatten.each do |v|
119
119
  section.option(opt, v)
@@ -83,6 +83,7 @@ class Chef
83
83
  source ::File.expand_path("support/ulimit.erb", __dir__)
84
84
  local true
85
85
  mode "0644"
86
+ sensitive new_resource.sensitive
86
87
  variables(
87
88
  ulimit_user: new_resource.username,
88
89
  filehandle_limit: new_resource.filehandle_limit,
@@ -17,6 +17,7 @@
17
17
  # limitations under the License.
18
18
 
19
19
  require_relative "../resource"
20
+ require "tempfile" unless defined?(Tempfile)
20
21
 
21
22
  class Chef
22
23
  class Resource
@@ -27,6 +28,7 @@ class Chef
27
28
 
28
29
  # The valid policy_names options found here
29
30
  # https://github.com/ChrisAWalker/cSecurityOptions under 'AccountSettings'
31
+ # This needs to be revisited - the list at the link above is non-exhaustive and is missing a couple of items
30
32
  policy_names = %w{LockoutDuration
31
33
  MaximumPasswordAge
32
34
  MinimumPasswordAge
@@ -35,6 +37,8 @@ class Chef
35
37
  PasswordHistorySize
36
38
  LockoutBadCount
37
39
  ResetLockoutCount
40
+ AuditPolicyChange
41
+ LockoutDuration
38
42
  RequireLogonToChangePassword
39
43
  ForceLogoffWhenHourExpire
40
44
  NewAdministratorName
@@ -43,7 +47,7 @@ class Chef
43
47
  LSAAnonymousNameLookup
44
48
  EnableAdminAccount
45
49
  EnableGuestAccount
46
- }
50
+ }
47
51
  description "Use the **windows_security_policy** resource to set a security policy on the Microsoft Windows platform."
48
52
  introduced "16.0"
49
53
 
@@ -83,6 +87,55 @@ class Chef
83
87
  description: "Policy value to be set for policy name."
84
88
 
85
89
  load_current_value do |desired|
90
+ current_state = load_security_options
91
+
92
+ if desired.secoption == "ResetLockoutCount"
93
+ if desired.secvalue.to_i > 30
94
+ raise Chef::Exceptions::ValidationFailed, "The \"ResetLockoutCount\" value cannot be greater than 30 minutes"
95
+ end
96
+ end
97
+ if (desired.secoption == "ResetLockoutCount" || desired.secoption == "LockoutDuration") && current_state["LockoutBadCount"] == "0"
98
+ raise Chef::Exceptions::ValidationFailed, "#{desired.secoption} cannot be set unless the \"LockoutBadCount\" security policy has been set to a non-zero value"
99
+ end
100
+
101
+ secvalue current_state[desired.secoption.to_s]
102
+ end
103
+
104
+ action :set do
105
+ converge_if_changed :secvalue do
106
+ security_option = new_resource.secoption
107
+ security_value = new_resource.secvalue
108
+
109
+ file = Tempfile.new(["#{security_option}", ".inf"])
110
+ case security_option
111
+ when "LockoutBadCount"
112
+ cmd = "net accounts /LockoutThreshold:#{security_value}"
113
+ when "ResetLockoutCount"
114
+ cmd = "net accounts /LockoutWindow:#{security_value}"
115
+ when "LockoutDuration"
116
+ cmd = "net accounts /LockoutDuration:#{security_value}"
117
+ when "NewAdministratorName", "NewGuestName"
118
+ policy_line = "#{security_option} = \"#{security_value}\""
119
+ file.write("[Unicode]\r\nUnicode=yes\r\n[System Access]\r\n#{policy_line}\r\n[Version]\r\nsignature=\"$CHICAGO$\"\r\nRevision=1\r\n")
120
+ file.close
121
+ file_path = file.path.gsub("/", '\\')
122
+ cmd = "C:\\Windows\\System32\\secedit /configure /db C:\\windows\\security\\new.sdb /cfg #{file_path} /areas SECURITYPOLICY"
123
+ else
124
+ policy_line = "#{security_option} = #{security_value}"
125
+ file.write("[Unicode]\r\nUnicode=yes\r\n[System Access]\r\n#{policy_line}\r\n[Version]\r\nsignature=\"$CHICAGO$\"\r\nRevision=1\r\n")
126
+ file.close
127
+ file_path = file.path.gsub("/", '\\')
128
+ cmd = "C:\\Windows\\System32\\secedit /configure /db C:\\windows\\security\\new.sdb /cfg #{file_path} /areas SECURITYPOLICY"
129
+ end
130
+ shell_out!(cmd)
131
+ file.unlink
132
+ end
133
+ end
134
+
135
+ private
136
+
137
+ # Loads powershell to get current state on security options
138
+ def load_security_options
86
139
  powershell_code = <<-CODE
87
140
  C:\\Windows\\System32\\secedit /export /cfg $env:TEMP\\secopts_export.inf | Out-Null
88
141
  # cspell:disable-next-line
@@ -108,44 +161,7 @@ class Chef
108
161
  LockoutBadCount = $security_options_hash.LockoutBadCount
109
162
  })
110
163
  CODE
111
- output = powershell_exec(powershell_code)
112
- current_value_does_not_exist! if output.result.empty?
113
- state = output.result
114
-
115
- if desired.secoption == "ResetLockoutCount" || desired.secoption == "LockoutDuration"
116
- if state["LockoutBadCount"] == "0"
117
- raise Chef::Exceptions::ValidationFailed.new "#{desired.secoption} cannot be set unless the \"LockoutBadCount\" security policy has been set to a non-zero value"
118
- else
119
- secvalue state[desired.secoption.to_s]
120
- end
121
- else
122
- secvalue state[desired.secoption.to_s]
123
- end
124
- end
125
-
126
- action :set do
127
- converge_if_changed :secvalue do
128
- security_option = new_resource.secoption
129
- security_value = new_resource.secvalue
130
-
131
- cmd = <<-EOH
132
- $security_option = "#{security_option}"
133
- C:\\Windows\\System32\\secedit /export /cfg $env:TEMP\\#{security_option}_Export.inf
134
- if ( ($security_option -match "NewGuestName") -Or ($security_option -match "NewAdministratorName") )
135
- {
136
- $#{security_option}_Remediation = (Get-Content $env:TEMP\\#{security_option}_Export.inf) | Foreach-Object { $_ -replace '#{security_option}\\s*=\\s*\\"\\w*\\"', '#{security_option} = "#{security_value}"' } | Set-Content $env:TEMP\\#{security_option}_Export.inf
137
- C:\\Windows\\System32\\secedit /configure /db $env:windir\\security\\new.sdb /cfg $env:TEMP\\#{security_option}_Export.inf /areas SECURITYPOLICY
138
- }
139
- else
140
- {
141
- $#{security_option}_Remediation = (Get-Content $env:TEMP\\#{security_option}_Export.inf) | Foreach-Object { $_ -replace "#{security_option}\\s*=\\s*\\d*", "#{security_option} = #{security_value}" } | Set-Content $env:TEMP\\#{security_option}_Export.inf
142
- C:\\Windows\\System32\\secedit /configure /db $env:windir\\security\\new.sdb /cfg $env:TEMP\\#{security_option}_Export.inf /areas SECURITYPOLICY
143
- }
144
- Remove-Item $env:TEMP\\#{security_option}_Export.inf -force
145
- EOH
146
-
147
- powershell_exec!(cmd)
148
- end
164
+ powershell_exec(powershell_code).result
149
165
  end
150
166
  end
151
167
  end
@@ -106,7 +106,9 @@ class Chef
106
106
  #
107
107
  # @return [Integer]
108
108
  def consent_behavior_users_symbol_to_reg(sym)
109
- %i{auto_deny secure_prompt_for_creds prompt_for_creds}.index(sym)
109
+ # Since 2 isn't a valid value for ConsentPromptBehaviorUser, assign the value at index as nil.
110
+ # https://docs.microsoft.com/en-us/windows/security/identity-protection/user-account-control/user-account-control-group-policy-and-registry-key-settings#registry-key-settings
111
+ [:auto_deny, :secure_prompt_for_creds, nil, :prompt_for_creds].index(sym)
110
112
  end
111
113
  end
112
114
  end
@@ -139,7 +139,7 @@ class Chef
139
139
  coerce: proc { |v| Array(v) },
140
140
  callbacks: {
141
141
  "Privilege property restricted to the following values: #{PRIVILEGE_OPTS}" => lambda { |n| (n - PRIVILEGE_OPTS).empty? },
142
- }
142
+ }, identity: true
143
143
 
144
144
  load_current_value do |new_resource|
145
145
  if new_resource.principal && (new_resource.action.include?(:add) || new_resource.action.include?(:remove))
data/lib/chef/resource.rb CHANGED
@@ -1513,7 +1513,7 @@ class Chef
1513
1513
  # @return Chef::CookbookVersion The cookbook in which this Resource was defined.
1514
1514
  #
1515
1515
  def cookbook_version
1516
- if cookbook_name
1516
+ if cookbook_name && cookbook_name != "@recipe_files"
1517
1517
  run_context.cookbook_collection[cookbook_name]
1518
1518
  end
1519
1519
  end
@@ -41,7 +41,7 @@ class Chef
41
41
  as_hash["result"] = action_record.action.to_s
42
42
  if new_resource.cookbook_name
43
43
  as_hash["cookbook_name"] = new_resource.cookbook_name
44
- as_hash["cookbook_version"] = new_resource.cookbook_version.version
44
+ as_hash["cookbook_version"] = new_resource.cookbook_version&.version
45
45
  end
46
46
 
47
47
  as_hash
@@ -198,9 +198,9 @@ module Shell
198
198
  prints a detailed explanation of the command if available, or the
199
199
  description if no explanation is available.
200
200
  E
201
- def help(commmand = nil)
202
- if commmand
203
- explain_command(commmand)
201
+ def help(command = nil)
202
+ if command
203
+ explain_command(command)
204
204
  else
205
205
  puts help_banner
206
206
  end
data/lib/chef/version.rb CHANGED
@@ -23,7 +23,7 @@ require_relative "version_string"
23
23
 
24
24
  class Chef
25
25
  CHEF_ROOT = File.expand_path("..", __dir__)
26
- VERSION = Chef::VersionString.new("16.14.1")
26
+ VERSION = Chef::VersionString.new("16.17.4")
27
27
  end
28
28
 
29
29
  #