chef 17.6.15 → 17.8.25

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -0
  3. data/chef.gemspec +1 -0
  4. data/lib/chef/application/base.rb +1 -1
  5. data/lib/chef/chef_fs/file_pattern.rb +1 -1
  6. data/lib/chef/chef_fs/path_utils.rb +1 -1
  7. data/lib/chef/compliance/default_attributes.rb +12 -2
  8. data/lib/chef/compliance/runner.rb +51 -5
  9. data/lib/chef/data_collector/run_end_message.rb +1 -1
  10. data/lib/chef/dsl/reboot_pending.rb +1 -1
  11. data/lib/chef/exceptions.rb +10 -0
  12. data/lib/chef/mixin/powershell_exec.rb +6 -5
  13. data/lib/chef/mixin/why_run.rb +8 -2
  14. data/lib/chef/powershell.rb +8 -6
  15. data/lib/chef/provider/cron.rb +4 -1
  16. data/lib/chef/provider/git.rb +1 -1
  17. data/lib/chef/provider/ifconfig/debian.rb +1 -1
  18. data/lib/chef/provider/mount/linux.rb +16 -2
  19. data/lib/chef/provider/mount/mount.rb +1 -1
  20. data/lib/chef/provider/package/dnf.rb +1 -1
  21. data/lib/chef/provider/package/habitat.rb +1 -1
  22. data/lib/chef/provider/package/powershell.rb +13 -10
  23. data/lib/chef/provider/package/zypper.rb +2 -0
  24. data/lib/chef/provider/package.rb +58 -23
  25. data/lib/chef/provider/subversion.rb +5 -5
  26. data/lib/chef/provider.rb +1 -1
  27. data/lib/chef/pwsh.rb +3 -2
  28. data/lib/chef/resource/chef_client_config.rb +22 -1
  29. data/lib/chef/resource/chef_client_launchd.rb +1 -1
  30. data/lib/chef/resource/chef_client_trusted_certificate.rb +1 -0
  31. data/lib/chef/resource/chocolatey_config.rb +1 -1
  32. data/lib/chef/resource/chocolatey_feature.rb +1 -1
  33. data/lib/chef/resource/chocolatey_source.rb +24 -2
  34. data/lib/chef/resource/directory.rb +1 -1
  35. data/lib/chef/resource/dnf_package.rb +4 -6
  36. data/lib/chef/resource/dpkg_package.rb +5 -0
  37. data/lib/chef/resource/execute.rb +1 -4
  38. data/lib/chef/resource/habitat_install.rb +5 -5
  39. data/lib/chef/resource/inspec_waiver.rb +1 -1
  40. data/lib/chef/resource/inspec_waiver_file_entry.rb +1 -1
  41. data/lib/chef/resource/kernel_module.rb +27 -2
  42. data/lib/chef/resource/launchd.rb +0 -3
  43. data/lib/chef/resource/macos_userdefaults.rb +41 -131
  44. data/lib/chef/resource/rhsm_register.rb +31 -0
  45. data/lib/chef/resource/support/client.erb +7 -0
  46. data/lib/chef/resource/windows_auto_run.rb +1 -1
  47. data/lib/chef/resource/windows_dfs_namespace.rb +2 -2
  48. data/lib/chef/resource/windows_feature_powershell.rb +7 -7
  49. data/lib/chef/resource/windows_update_settings.rb +3 -3
  50. data/lib/chef/resource.rb +2 -2
  51. data/lib/chef/resource_reporter.rb +1 -1
  52. data/lib/chef/secret_fetcher/azure_key_vault.rb +62 -8
  53. data/lib/chef/secret_fetcher.rb +0 -1
  54. data/lib/chef/version.rb +1 -1
  55. data/spec/functional/dsl/reboot_pending_spec.rb +3 -3
  56. data/spec/functional/dsl/registry_helper_spec.rb +1 -1
  57. data/spec/functional/resource/dnf_package_spec.rb +34 -20
  58. data/spec/functional/resource/dpkg_package_spec.rb +16 -0
  59. data/spec/functional/resource/dsc_script_spec.rb +2 -2
  60. data/spec/functional/resource/macos_userdefaults_spec.rb +139 -0
  61. data/spec/functional/resource/registry_spec.rb +81 -81
  62. data/spec/functional/resource/zypper_package_spec.rb +7 -0
  63. data/spec/functional/win32/registry_spec.rb +8 -8
  64. data/spec/integration/client/client_spec.rb +31 -0
  65. data/spec/unit/application/base_spec.rb +40 -0
  66. data/spec/unit/compliance/runner_spec.rb +62 -1
  67. data/spec/unit/data_collector_spec.rb +24 -1
  68. data/spec/unit/dsl/reboot_pending_spec.rb +1 -1
  69. data/spec/unit/file_access_control_spec.rb +1 -1
  70. data/spec/unit/mixin/default_paths_spec.rb +1 -1
  71. data/spec/unit/mixin/securable_spec.rb +3 -3
  72. data/spec/unit/mixin/why_run_spec.rb +53 -0
  73. data/spec/unit/provider/cron_spec.rb +45 -0
  74. data/spec/unit/provider/group/groupadd_spec.rb +1 -0
  75. data/spec/unit/provider/group/usermod_spec.rb +2 -2
  76. data/spec/unit/provider/ifconfig_spec.rb +2 -0
  77. data/spec/unit/provider/mount/linux_spec.rb +16 -3
  78. data/spec/unit/provider/package/bff_spec.rb +1 -0
  79. data/spec/unit/provider/package/powershell_spec.rb +114 -114
  80. data/spec/unit/provider/package/rubygems_spec.rb +8 -5
  81. data/spec/unit/provider/package/solaris_spec.rb +1 -0
  82. data/spec/unit/provider/package/windows_spec.rb +1 -1
  83. data/spec/unit/provider/registry_key_spec.rb +4 -4
  84. data/spec/unit/provider/service/arch_service_spec.rb +2 -2
  85. data/spec/unit/provider/service/debian_service_spec.rb +1 -0
  86. data/spec/unit/provider/service/gentoo_service_spec.rb +1 -0
  87. data/spec/unit/provider/service/macosx_spec.rb +1 -0
  88. data/spec/unit/provider/service/redhat_spec.rb +4 -1
  89. data/spec/unit/provider/service/simple_service_spec.rb +6 -4
  90. data/spec/unit/provider/service/windows_spec.rb +5 -5
  91. data/spec/unit/provider/subversion_spec.rb +4 -4
  92. data/spec/unit/provider/user_spec.rb +2 -0
  93. data/spec/unit/provider/windows_env_spec.rb +1 -1
  94. data/spec/unit/provider/zypper_repository_spec.rb +1 -1
  95. data/spec/unit/resource/chef_client_trusted_certificate_spec.rb +14 -0
  96. data/spec/unit/resource/chocolatey_config_spec.rb +1 -1
  97. data/spec/unit/resource/chocolatey_feature_spec.rb +1 -1
  98. data/spec/unit/resource/chocolatey_source_spec.rb +1 -1
  99. data/spec/unit/resource/dpkg_package_spec.rb +12 -0
  100. data/spec/unit/resource/kernel_module_spec.rb +2 -1
  101. data/spec/unit/resource/macos_user_defaults_spec.rb +36 -96
  102. data/spec/unit/resource/registry_key_spec.rb +10 -10
  103. data/spec/unit/resource/rhsm_register_spec.rb +42 -0
  104. data/spec/unit/resource/windows_auto_run_spec.rb +1 -1
  105. data/spec/unit/resource/windows_feature_powershell_spec.rb +1 -1
  106. data/spec/unit/resource/windows_firewall_rule_spec.rb +2 -2
  107. data/spec/unit/resource/windows_task_spec.rb +3 -3
  108. data/spec/unit/resource_reporter_spec.rb +2 -2
  109. data/spec/unit/resource_spec.rb +5 -0
  110. data/spec/unit/secret_fetcher/azure_key_vault_spec.rb +99 -20
  111. data/spec/unit/util/backup_spec.rb +1 -1
  112. data/spec/unit/win32/registry_spec.rb +3 -3
  113. metadata +24 -7
@@ -17,6 +17,7 @@
17
17
 
18
18
  require_relative "../resource"
19
19
  require "chef-utils/dist" unless defined?(ChefUtils::Dist)
20
+ require "corefoundation" if RUBY_PLATFORM.match?(/darwin/)
20
21
  autoload :Plist, "plist"
21
22
 
22
23
  class Chef
@@ -78,173 +79,82 @@ class Chef
78
79
  required: true
79
80
 
80
81
  property :host, [String, Symbol],
81
- description: "Set either :current or a hostname to set the user default at the host level.",
82
+ description: "Set either :current, :all or a hostname to set the user default at the host level.",
82
83
  desired_state: false,
83
84
  introduced: "16.3"
84
85
 
85
86
  property :value, [Integer, Float, String, TrueClass, FalseClass, Hash, Array],
86
87
  description: "The value of the key. Note: With the `type` property set to `bool`, `String` forms of Boolean true/false values that Apple accepts in the defaults command will be coerced: 0/1, 'TRUE'/'FALSE,' 'true'/false', 'YES'/'NO', or 'yes'/'no'.",
87
- required: [:write],
88
- coerce: proc { |v| v.is_a?(Hash) ? v.transform_keys(&:to_s) : v } # make sure keys are all strings for comparison
88
+ required: [:write]
89
89
 
90
90
  property :type, String,
91
91
  description: "The value type of the preference key.",
92
92
  equal_to: %w{bool string int float array dict},
93
- desired_state: false
93
+ desired_state: false,
94
+ deprecated: true
94
95
 
95
- property :user, String,
96
- description: "The system user that the default will be applied to.",
96
+ property :user, [String, Symbol],
97
+ description: "The system user that the default will be applied to. Set :current for current user, :all for all users or pass a valid username",
97
98
  desired_state: false
98
99
 
99
100
  property :sudo, [TrueClass, FalseClass],
100
101
  description: "Set to true if the setting you wish to modify requires privileged access. This requires passwordless sudo for the `/usr/bin/defaults` command to be setup for the user running #{ChefUtils::Dist::Infra::PRODUCT}.",
101
102
  default: false,
102
- desired_state: false
103
+ desired_state: false,
104
+ deprecated: true
103
105
 
104
106
  load_current_value do |new_resource|
105
- Chef::Log.debug "#load_current_value: shelling out \"#{defaults_export_cmd(new_resource).join(" ")}\" to determine state"
106
- state = shell_out(defaults_export_cmd(new_resource), user: new_resource.user)
107
-
108
- if state.error? || state.stdout.empty?
109
- Chef::Log.debug "#load_current_value: #{defaults_export_cmd(new_resource).join(" ")} returned stdout: #{state.stdout} and stderr: #{state.stderr}"
110
- current_value_does_not_exist!
111
- end
107
+ Chef::Log.debug "#load_current_value: attempting to read \"#{new_resource.domain}\" value from preferences to determine state"
112
108
 
113
- plist_data = ::Plist.parse_xml(state.stdout)
109
+ pref = get_preference(new_resource)
110
+ current_value_does_not_exist! if pref.nil?
114
111
 
115
- # handle the situation where the key doesn't exist in the domain
116
- if plist_data.key?(new_resource.key)
117
- key new_resource.key
118
- else
119
- current_value_does_not_exist!
120
- end
121
-
122
- value plist_data[new_resource.key]
123
- end
124
-
125
- #
126
- # The defaults command to export a domain
127
- #
128
- # @return [Array] defaults command
129
- #
130
- def defaults_export_cmd(resource)
131
- state_cmd = ["/usr/bin/defaults"]
132
-
133
- if resource.host == "current"
134
- state_cmd.concat(["-currentHost"])
135
- elsif resource.host # they specified a non-nil value, which is a hostname
136
- state_cmd.concat(["-host", resource.host])
137
- end
138
-
139
- state_cmd.concat(["export", resource.domain, "-"])
140
- state_cmd
112
+ key new_resource.key
113
+ value pref
141
114
  end
142
115
 
143
116
  action :write, description: "Write the value to the specified domain/key." do
144
117
  converge_if_changed do
145
- cmd = defaults_modify_cmd
146
- Chef::Log.debug("Updating defaults value by shelling out: #{cmd.join(" ")}")
147
-
148
- shell_out!(cmd, user: new_resource.user)
118
+ Chef::Log.debug("Updating defaults value for #{new_resource.key} in #{new_resource.domain}")
119
+ CF::Preferences.set!(new_resource.key, new_resource.value, new_resource.domain, to_cf_user(new_resource.user), to_cf_host(new_resource.host))
149
120
  end
150
121
  end
151
122
 
152
123
  action :delete, description: "Delete a key from a domain." do
153
124
  # if it's not there there's nothing to remove
154
- return unless current_resource
125
+ return if current_resource.nil?
155
126
 
156
127
  converge_by("delete domain:#{new_resource.domain} key:#{new_resource.key}") do
157
-
158
- cmd = defaults_modify_cmd
159
- Chef::Log.debug("Removing defaults key by shelling out: #{cmd.join(" ")}")
160
-
161
- shell_out!(cmd, user: new_resource.user)
128
+ Chef::Log.debug("Removing defaults key: #{new_resource.key}")
129
+ CF::Preferences.set!(new_resource.key, nil, new_resource.domain, to_cf_user(new_resource.user), to_cf_host(new_resource.host))
162
130
  end
163
131
  end
164
132
 
165
- action_class do
166
- #
167
- # The command used to write or delete delete values from domains
168
- #
169
- # @return [Array] Array representation of defaults command to run
170
- #
171
- def defaults_modify_cmd
172
- cmd = ["/usr/bin/defaults"]
173
-
174
- if new_resource.host == :current
175
- cmd.concat(["-currentHost"])
176
- elsif new_resource.host # they specified a non-nil value, which is a hostname
177
- cmd.concat(["-host", new_resource.host])
178
- end
179
-
180
- cmd.concat([action.to_s, new_resource.domain, new_resource.key])
181
- cmd.concat(processed_value) if action == :write
182
- cmd.prepend("sudo") if new_resource.sudo
183
- cmd
184
- end
185
-
186
- #
187
- # convert the provided value into the format defaults expects
188
- #
189
- # @return [array] array of values starting with the type if applicable
190
- #
191
- def processed_value
192
- type = new_resource.type || value_type(new_resource.value)
193
-
194
- # when dict this creates an array of values ["Key1", "Value1", "Key2", "Value2" ...]
195
- cmd_values = ["-#{type}"]
196
-
197
- case type
198
- when "dict"
199
- cmd_values.concat(new_resource.value.flatten)
200
- when "array"
201
- cmd_values.concat(new_resource.value)
202
- when "bool"
203
- cmd_values.concat(bool_to_defaults_bool(new_resource.value))
204
- else
205
- cmd_values.concat([new_resource.value])
206
- end
207
-
208
- cmd_values
209
- end
133
+ def get_preference(new_resource)
134
+ CF::Preferences.get(new_resource.key, new_resource.domain, to_cf_user(new_resource.user), to_cf_host(new_resource.host))
135
+ end
210
136
 
211
- #
212
- # defaults booleans on the CLI must be 'TRUE' or 'FALSE' so convert various inputs to that
213
- #
214
- # @param [String, Integer, Boolean] input <description>
215
- #
216
- # @return [String] TRUE or FALSE
217
- #
218
- def bool_to_defaults_bool(input)
219
- return ["TRUE"] if [true, "TRUE", "1", "true", "YES", "yes"].include?(input)
220
- return ["FALSE"] if [false, "FALSE", "0", "false", "NO", "no"].include?(input)
221
-
222
- # make sure it's very clear bad input was given
223
- raise ArgumentError, "#{input} cannot be converted to a boolean value for use with Apple's defaults command. Acceptable values are: 'TRUE', 'YES', 'true, 'yes', '0', true, 'FALSE', 'false', 'NO', 'no', '1', or false."
137
+ # Return valid hostname based on the input from host property
138
+ def to_cf_host(value)
139
+ case value
140
+ when :all
141
+ CF::Preferences::ALL_HOSTS
142
+ when :current
143
+ CF::Preferences::CURRENT_HOST
144
+ else
145
+ value
224
146
  end
147
+ end
225
148
 
226
- #
227
- # convert ruby type to defaults type
228
- #
229
- # @param [Integer, Float, String, TrueClass, FalseClass, Hash, Array] value The value being set
230
- #
231
- # @return [string, nil] the type value used by defaults or nil if not applicable
232
- #
233
- def value_type(value)
234
- case value
235
- when true, false
236
- "bool"
237
- when Integer
238
- "int"
239
- when Float
240
- "float"
241
- when Hash
242
- "dict"
243
- when Array
244
- "array"
245
- when String
246
- "string"
247
- end
149
+ # Return valid username based on the input from user property
150
+ def to_cf_user(value)
151
+ case value
152
+ when :all
153
+ CF::Preferences::ALL_USERS
154
+ when :current
155
+ CF::Preferences::CURRENT_USER
156
+ else
157
+ value
248
158
  end
249
159
  end
250
160
  end
@@ -79,6 +79,23 @@ class Chef
79
79
  default: false, desired_state: false,
80
80
  introduced: "15.9"
81
81
 
82
+ property :server_url, String,
83
+ description: "The hostname of the subscription service to use. The default is for Customer Portal Subscription Management, subscription.rhn.redhat.com. If this option is not used, the system is registered with Customer Portal Subscription Management.",
84
+ introduced: "17.8"
85
+
86
+ property :base_url, String,
87
+ description: "The hostname of the content delivery server to use to receive updates. Both Customer Portal Subscription Management and Subscription Asset Manager use Red Hat's hosted content delivery services, with the URL https://cdn.redhat.com. Since Satellite 6 hosts its own content, the URL must be used for systems registered with Satellite 6.",
88
+ introduced: "17.8"
89
+
90
+ property :service_level, String,
91
+ description: "Sets the service level to use for subscriptions on the registering machine. This is only used with the auto_attach option.",
92
+ introduced: "17.8"
93
+
94
+ property :release,
95
+ [Float, String],
96
+ description: "Sets the operating system minor release to use for subscriptions for the system. Products and updates are limited to the specified minor release version. This is used only used with the auto_attach option. For example, `release '6.4'` will append `--release=6.4` to the register command.",
97
+ introduced: "17.8"
98
+
82
99
  action :register, description: "Register the node with RHSM." do
83
100
  package "subscription-manager"
84
101
 
@@ -170,6 +187,8 @@ class Chef
170
187
  command << new_resource.activation_key.map { |key| "--activationkey=#{Shellwords.shellescape(key)}" }
171
188
  command << "--org=#{Shellwords.shellescape(new_resource.organization)}"
172
189
  command << "--name=#{Shellwords.shellescape(new_resource.system_name)}" if new_resource.system_name
190
+ command << "--serverurl=#{Shellwords.shellescape(new_resource.server_url)}" if new_resource.server_url
191
+ command << "--baseurl=#{Shellwords.shellescape(new_resource.base_url)}" if new_resource.base_url
173
192
  command << "--force" if new_resource.force
174
193
 
175
194
  return command.join(" ")
@@ -179,11 +198,23 @@ class Chef
179
198
  if new_resource.username && new_resource.password
180
199
  raise "Unable to register - you must specify environment when using username/password" if new_resource.environment.nil? && using_satellite_host?
181
200
 
201
+ if new_resource.service_level
202
+ raise "Unable to register - 'auto_attach' must be enabled when using property `service_level`." unless new_resource.auto_attach
203
+ end
204
+
205
+ if new_resource.release
206
+ raise "Unable to register - `auto_attach` must be enabled when using property `release`." unless new_resource.auto_attach
207
+ end
208
+
182
209
  command << "--username=#{Shellwords.shellescape(new_resource.username)}"
183
210
  command << "--password=#{Shellwords.shellescape(new_resource.password)}"
184
211
  command << "--environment=#{Shellwords.shellescape(new_resource.environment)}" if using_satellite_host?
185
212
  command << "--name=#{Shellwords.shellescape(new_resource.system_name)}" if new_resource.system_name
213
+ command << "--serverurl=#{Shellwords.shellescape(new_resource.server_url)}" if new_resource.server_url
214
+ command << "--baseurl=#{Shellwords.shellescape(new_resource.base_url)}" if new_resource.base_url
186
215
  command << "--auto-attach" if new_resource.auto_attach
216
+ command << "--servicelevel=#{Shellwords.shellescape(new_resource.service_level)}" if new_resource.service_level
217
+ command << "--release=#{Shellwords.shellescape(new_resource.release)}" if new_resource.release
187
218
  command << "--force" if new_resource.force
188
219
 
189
220
  return command.join(" ")
@@ -37,6 +37,13 @@ log_location <%= @log_location %>
37
37
  log_location <%= @log_location.inspect %>
38
38
  <% end -%>
39
39
  <% end -%>
40
+ <%# These data_collector options are special as they have a '.' -%>
41
+ <% unless @data_collector_server_url.nil? || @data_collector_server_url.empty? %>
42
+ data_collector.server_url <%= @data_collector_server_url %>
43
+ <% end %>
44
+ <% unless @data_collector_token.nil? || @data_collector_token.empty? %>
45
+ data_collector.token <%= @data_collector_token %>
46
+ <% end %>
40
47
  <%# The code below is not DRY on purpose to improve readability -%>
41
48
  <% unless @start_handlers.empty? -%>
42
49
  # Do not crash if a start handler is missing / not installed yet
@@ -88,7 +88,7 @@ class Chef
88
88
  # @return [String]
89
89
  def registry_path
90
90
  { machine: "HKLM", user: "HKCU" }[new_resource.root] + \
91
- '\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run'
91
+ "\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"
92
92
  end
93
93
  end
94
94
  end
@@ -38,7 +38,7 @@ class Chef
38
38
 
39
39
  property :full_users, Array,
40
40
  description: "Determines which users should have full access to the share.",
41
- default: ['BUILTIN\\administrators']
41
+ default: ["BUILTIN\\administrators"]
42
42
 
43
43
  property :change_users, Array,
44
44
  description: "Determines which users should have change access to the share.",
@@ -50,7 +50,7 @@ class Chef
50
50
 
51
51
  property :root, String,
52
52
  description: "The root from which to create the DFS tree. Defaults to C:\\DFSRoots.",
53
- default: 'C:\\DFSRoots'
53
+ default: "C:\\DFSRoots"
54
54
 
55
55
  action :create, description: "Creates the dfs namespace on the server." do
56
56
  directory file_path do
@@ -100,8 +100,8 @@ class Chef
100
100
  install_command << " -Source \"#{new_resource.source}\"" if new_resource.source
101
101
  install_command << " -IncludeManagementTools" if new_resource.management_tools
102
102
 
103
- cmd = powershell_out!(install_command, timeout: new_resource.timeout)
104
- Chef::Log.info(cmd.stdout)
103
+ cmd = powershell_exec!(install_command, timeout: new_resource.timeout)
104
+ Chef::Log.info(cmd.result)
105
105
 
106
106
  reload_cached_powershell_data # Reload cached powershell feature state
107
107
  end
@@ -115,8 +115,8 @@ class Chef
115
115
 
116
116
  unless features_to_remove.empty?
117
117
  converge_by("remove Windows feature#{"s" if features_to_remove.count > 1} #{features_to_remove.join(",")}") do
118
- cmd = powershell_out!("Uninstall-WindowsFeature #{features_to_remove.join(",")}", timeout: new_resource.timeout)
119
- Chef::Log.info(cmd.stdout)
118
+ cmd = powershell_exec!("Uninstall-WindowsFeature #{features_to_remove.join(",")}", timeout: new_resource.timeout)
119
+ Chef::Log.info(cmd.result)
120
120
 
121
121
  reload_cached_powershell_data # Reload cached powershell feature state
122
122
  end
@@ -132,8 +132,8 @@ class Chef
132
132
 
133
133
  unless features_to_delete.empty?
134
134
  converge_by("delete Windows feature#{"s" if features_to_delete.count > 1} #{features_to_delete.join(",")} from the image") do
135
- cmd = powershell_out!("Uninstall-WindowsFeature #{features_to_delete.join(",")} -Remove", timeout: new_resource.timeout)
136
- Chef::Log.info(cmd.stdout)
135
+ cmd = powershell_exec!("Uninstall-WindowsFeature #{features_to_delete.join(",")} -Remove", timeout: new_resource.timeout)
136
+ Chef::Log.info(cmd.result)
137
137
 
138
138
  reload_cached_powershell_data # Reload cached powershell feature state
139
139
  end
@@ -215,7 +215,7 @@ class Chef
215
215
  # fetch the list of available feature names and state in JSON and parse the JSON
216
216
  def parsed_feature_list
217
217
  # Grab raw feature information from WindowsFeature
218
- raw_list_of_features = powershell_out!("Get-WindowsFeature | Select-Object -Property Name,InstallState | ConvertTo-Json -Compress", timeout: new_resource.timeout).stdout
218
+ raw_list_of_features = powershell_exec!("Get-WindowsFeature | Select-Object -Property Name,InstallState", timeout: new_resource.timeout).result
219
219
 
220
220
  Chef::JSONCompat.from_json(raw_list_of_features)
221
221
  end
@@ -145,7 +145,7 @@ class Chef
145
145
  action :set, description: "Set Windows Update settings." do
146
146
  actual_day = convert_day(new_resource.scheduled_install_day)
147
147
 
148
- registry_key 'HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows\\WindowsUpdate' do
148
+ registry_key "HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows\\WindowsUpdate" do
149
149
  recursive true
150
150
  values [{
151
151
  name: "DisableOSUpgrade",
@@ -180,7 +180,7 @@ class Chef
180
180
  action :create
181
181
  end
182
182
 
183
- registry_key 'HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer' do
183
+ registry_key "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer" do
184
184
  recursive true
185
185
  values [{
186
186
  name: "NoWindowsUpdate",
@@ -190,7 +190,7 @@ class Chef
190
190
  action :create
191
191
  end
192
192
 
193
- registry_key 'HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU' do
193
+ registry_key "HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU" do
194
194
  recursive true
195
195
  values [{
196
196
  name: "AUOptions",
data/lib/chef/resource.rb CHANGED
@@ -454,7 +454,7 @@ class Chef
454
454
  # @param arg [String] The umask to apply while converging the resource.
455
455
  # @return [Boolean] The umask to apply while converging the resource.
456
456
  #
457
- property :umask, String,
457
+ property :umask, [String, Integer],
458
458
  desired_state: false,
459
459
  introduced: "16.2",
460
460
  description: "Set a umask to be used for the duration of converging the resource. Defaults to `nil`, which means to use the system umask. Unsupported on Windows because Windows lacks a direct equivalent to UNIX's umask."
@@ -1508,7 +1508,7 @@ class Chef
1508
1508
  # @return Chef::CookbookVersion The cookbook in which this Resource was defined.
1509
1509
  #
1510
1510
  def cookbook_version
1511
- if cookbook_name
1511
+ if cookbook_name && cookbook_name != "@recipe_files"
1512
1512
  run_context.cookbook_collection[cookbook_name]
1513
1513
  end
1514
1514
  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
@@ -1,4 +1,6 @@
1
1
  require_relative "base"
2
+ require_relative "../exceptions"
3
+ require "uri" unless defined?(URI)
2
4
 
3
5
  class Chef
4
6
  class SecretFetcher
@@ -14,13 +16,19 @@ class Chef
14
16
  #
15
17
  # @example
16
18
  #
17
- # fetcher = SecretFetcher.for_service(:azure_key_vault, { vault: "my_vault" }, run_context )
19
+ # fetcher = SecretFetcher.for_service(:azure_key_vault, { vault: "my_vault" }, run_context)
18
20
  # fetcher.fetch("secretkey1", "v1")
19
21
  #
20
22
  # @example
21
23
  #
22
- # fetcher = SecretFetcher.for_service(:azure_key_vault, {}, run_context )
24
+ # fetcher = SecretFetcher.for_service(:azure_key_vault, {}, run_context)
23
25
  # fetcher.fetch("my_vault/secretkey1", "v1")
26
+ #
27
+ # @example
28
+ #
29
+ # fetcher = SecretFetcher.for_service(:azure_key_vault, { client_id: "540d76b6-7f76-456c-b68b-ccae4dc9d99d" }, run_context)
30
+ # fetcher.fetch("my_vault/secretkey1", "v1")
31
+ #
24
32
  class AzureKeyVault < Base
25
33
 
26
34
  def do_fetch(name, version)
@@ -48,6 +56,12 @@ class Chef
48
56
  end
49
57
  end
50
58
 
59
+ def validate!
60
+ raise Chef::Exceptions::Secret::ConfigurationInvalid, "You may only specify one (these are mutually exclusive): :object_id, :client_id, or :mi_res_id" if [object_id, client_id, mi_res_id].select { |x| !x.nil? }.length > 1
61
+ end
62
+
63
+ private
64
+
51
65
  # Determine the vault name and secret name from the provided name.
52
66
  # If it is not in the provided name in the form "vault_name/secret_name"
53
67
  # it will determine the vault name from `config[:vault]`.
@@ -63,16 +77,56 @@ class Chef
63
77
  end
64
78
  end
65
79
 
80
+ def api_version
81
+ "2018-02-01"
82
+ end
83
+
84
+ def resource
85
+ "https://vault.azure.net"
86
+ end
87
+
88
+ def object_id
89
+ config[:object_id]
90
+ end
91
+
92
+ def client_id
93
+ config[:client_id]
94
+ end
95
+
96
+ def mi_res_id
97
+ config[:mi_res_id]
98
+ end
99
+
100
+ def token_query
101
+ @token_query ||= begin
102
+ p = {}
103
+ p["api-version"] = api_version
104
+ p["resource"] = resource
105
+ p["object_id"] = object_id if object_id
106
+ p["client_id"] = client_id if client_id
107
+ p["mi_res_id"] = mi_res_id if mi_res_id
108
+ URI.encode_www_form(p)
109
+ end
110
+ end
111
+
66
112
  def fetch_token
67
- token_uri = URI.parse("http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fvault.azure.net")
113
+ token_uri = URI.parse("http://169.254.169.254/metadata/identity/oauth2/token")
114
+ token_uri.query = token_query
68
115
  http = Net::HTTP.new(token_uri.host, token_uri.port)
69
116
  response = http.get(token_uri, { "Metadata" => "true" })
70
- body = JSON.parse(response.body)
71
- body["access_token"]
117
+
118
+ case response
119
+ when Net::HTTPSuccess
120
+ body = JSON.parse(response.body)
121
+ body["access_token"]
122
+ when Net::HTTPBadRequest
123
+ body = JSON.parse(response.body)
124
+ raise Chef::Exceptions::Secret::Azure::IdentityNotFound if body["error_description"] =~ /identity not found/i
125
+ else
126
+ body = JSON.parse(response.body)
127
+ body["access_token"]
128
+ end
72
129
  end
73
130
  end
74
131
  end
75
132
  end
76
-
77
-
78
-
@@ -58,4 +58,3 @@ class Chef
58
58
  end
59
59
  end
60
60
  end
61
-
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("17.6.15")
26
+ VERSION = Chef::VersionString.new("17.8.25")
27
27
  end
28
28
 
29
29
  #
@@ -39,8 +39,8 @@ describe Chef::DSL::RebootPending, :windows_only do
39
39
  let(:reg_key) { nil }
40
40
  let(:original_set) { false }
41
41
 
42
- describe 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations' do
43
- let(:reg_key) { 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager' }
42
+ describe "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\PendingFileRenameOperations" do
43
+ let(:reg_key) { "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager" }
44
44
  let(:original_set) { registry.value_exists?(reg_key, { name: "PendingFileRenameOperations" }) }
45
45
 
46
46
  it "returns true if the registry value exists" do
@@ -78,7 +78,7 @@ describe Chef::DSL::RebootPending, :windows_only do
78
78
 
79
79
  describe "when there is nothing to indicate a reboot is pending" do
80
80
  it "should return false" do
81
- skip "reboot pending" if registry_value_exists?('HKLM\SYSTEM\CurrentControlSet\Control\Session Manager', { name: "PendingFileRenameOperations" }) ||
81
+ skip "reboot pending" if registry_value_exists?("HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager", { name: "PendingFileRenameOperations" }) ||
82
82
  registry_key_exists?('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired') ||
83
83
  registry_key_exists?('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending')
84
84
  expect(recipe.reboot_pending?).to be_falsey
@@ -24,7 +24,7 @@ describe Chef::Resource::RegistryKey, :windows_only do
24
24
  before(:all) do
25
25
  ::Win32::Registry::HKEY_CURRENT_USER.create "Software\\Root"
26
26
  ::Win32::Registry::HKEY_CURRENT_USER.create "Software\\Root\\Branch"
27
- ::Win32::Registry::HKEY_CURRENT_USER.open('Software\\Root', Win32::Registry::KEY_ALL_ACCESS) do |reg|
27
+ ::Win32::Registry::HKEY_CURRENT_USER.open("Software\\Root", Win32::Registry::KEY_ALL_ACCESS) do |reg|
28
28
  reg["RootType1", Win32::Registry::REG_SZ] = "fibrous"
29
29
  reg.write("Roots", Win32::Registry::REG_MULTI_SZ, ["strong roots", "healthy tree"])
30
30
  end
@@ -455,7 +455,7 @@ describe Chef::Resource::DnfPackage, :requires_root, external: exclude_test do
455
455
  end
456
456
 
457
457
  context "downgrades" do
458
- it "downgrades the package when allow_downgrade" do
458
+ it "downgrades the package when allow_downgrade is true" do
459
459
  flush_cache
460
460
  preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
461
461
  dnf_package "chef_rpm" do
@@ -470,6 +470,18 @@ describe Chef::Resource::DnfPackage, :requires_root, external: exclude_test do
470
470
  action :install
471
471
  end.should_not_be_updated
472
472
  end
473
+
474
+ it "does not downgrade the package when allow_downgrade is false" do
475
+ flush_cache
476
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
477
+ dnf_package "chef_rpm" do
478
+ options default_options
479
+ allow_downgrade false
480
+ version "1.2-1"
481
+ action :install
482
+ end.should_not_be_updated
483
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.10-1.#{pkg_arch}$")
484
+ end
473
485
  end
474
486
 
475
487
  context "with arches", :intel_64bit do
@@ -763,6 +775,17 @@ describe Chef::Resource::DnfPackage, :requires_root, external: exclude_test do
763
775
  end.should_not_be_updated
764
776
  end
765
777
 
778
+ it "downgrade on a local file with allow_downgrade false does not downgrade" do
779
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
780
+ dnf_package "#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm" do
781
+ options default_options
782
+ allow_downgrade false
783
+ version "1.2-1"
784
+ action :install
785
+ end.should_not_be_updated
786
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.10-1.#{pkg_arch}$")
787
+ end
788
+
766
789
  it "does not downgrade the package with :install" do
767
790
  preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
768
791
  dnf_package "#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm" do
@@ -1027,25 +1050,6 @@ describe Chef::Resource::DnfPackage, :requires_root, external: exclude_test do
1027
1050
  action :install
1028
1051
  end.should_not_be_updated
1029
1052
  end
1030
-
1031
- it "throws a deprecation warning with allow_downgrade" do
1032
- Chef::Config[:treat_deprecation_warnings_as_errors] = false
1033
- expect(Chef).to receive(:deprecated).at_least(:once).with(:dnf_package_allow_downgrade, /^the allow_downgrade property on the dnf_package provider is not used/)
1034
- preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
1035
- dnf_package "chef_rpm" do
1036
- options default_options
1037
- version "1.2"
1038
- allow_downgrade true
1039
- action :install
1040
- end.should_be_updated
1041
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}")
1042
- dnf_package "chef_rpm" do
1043
- options default_options
1044
- version "1.2"
1045
- allow_downgrade true
1046
- action :install
1047
- end.should_not_be_updated
1048
- end
1049
1053
  end
1050
1054
 
1051
1055
  context "with source arguments" do
@@ -1092,6 +1096,16 @@ describe Chef::Resource::DnfPackage, :requires_root, external: exclude_test do
1092
1096
  end.should_not_be_updated
1093
1097
  end
1094
1098
 
1099
+ it "does not downgrade the package when allow_downgrade is false" do
1100
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
1101
+ dnf_package "#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm" do
1102
+ options default_options
1103
+ allow_downgrade false
1104
+ action :upgrade
1105
+ end.should_not_be_updated
1106
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.10-1.#{pkg_arch}$")
1107
+ end
1108
+
1095
1109
  it "upgrades the package" do
1096
1110
  preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
1097
1111
  dnf_package "#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.10-1.#{pkg_arch}.rpm" do