chef 17.9.52 → 18.0.169

Sign up to get free protection for your applications and to get access to all the features.
Files changed (311) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +16 -8
  3. data/README.md +7 -7
  4. data/Rakefile +5 -24
  5. data/{chef-universal-mingw32.gemspec → chef-universal-mingw-ucrt.gemspec} +7 -5
  6. data/chef.gemspec +14 -7
  7. data/lib/chef/api_client.rb +1 -1
  8. data/lib/chef/api_client_v1.rb +9 -1
  9. data/lib/chef/application/exit_code.rb +3 -3
  10. data/lib/chef/client.rb +167 -0
  11. data/lib/chef/compliance/input.rb +1 -1
  12. data/lib/chef/compliance/input_collection.rb +1 -1
  13. data/lib/chef/compliance/profile.rb +1 -1
  14. data/lib/chef/compliance/profile_collection.rb +1 -2
  15. data/lib/chef/compliance/waiver.rb +1 -1
  16. data/lib/chef/compliance/waiver_collection.rb +1 -1
  17. data/lib/chef/cookbook/syntax_check.rb +2 -2
  18. data/lib/chef/dsl/reader_helpers.rb +1 -1
  19. data/lib/chef/dsl/rest_resource.rb +77 -0
  20. data/lib/chef/dsl/secret.rb +113 -5
  21. data/lib/chef/event_dispatch/base.rb +3 -0
  22. data/lib/chef/exceptions.rb +8 -0
  23. data/lib/chef/http/authenticator.rb +170 -3
  24. data/lib/chef/http/ssl_policies.rb +3 -3
  25. data/lib/chef/mixin/powershell_exec.rb +5 -28
  26. data/lib/chef/mixin/properties.rb +6 -0
  27. data/lib/chef/node/attribute.rb +20 -3
  28. data/lib/chef/node/mixin/deep_merge_cache.rb +4 -4
  29. data/lib/chef/node/mixin/immutablize_array.rb +1 -0
  30. data/lib/chef/policy_builder/expand_node_object.rb +1 -2
  31. data/lib/chef/policy_builder/policyfile.rb +1 -1
  32. data/lib/chef/property.rb +5 -3
  33. data/lib/chef/provider/group/windows.rb +1 -1
  34. data/lib/chef/provider/http_request.rb +11 -9
  35. data/lib/chef/provider/mount/linux.rb +5 -0
  36. data/lib/chef/provider/mount/mount.rb +8 -0
  37. data/lib/chef/provider/mount/windows.rb +1 -1
  38. data/lib/chef/provider/package/powershell.rb +1 -1
  39. data/lib/chef/provider/package/rubygems.rb +7 -7
  40. data/lib/chef/provider/package/windows/msi.rb +2 -2
  41. data/lib/chef/provider/package/windows/registry_uninstall_entry.rb +1 -1
  42. data/lib/chef/provider/package/yum/python_helper.rb +14 -1
  43. data/lib/chef/provider/package/zypper/version.rb +60 -0
  44. data/lib/chef/provider/package/zypper.rb +47 -3
  45. data/lib/chef/provider/service/windows.rb +5 -5
  46. data/lib/chef/provider/user/aix.rb +5 -0
  47. data/lib/chef/provider/user/linux.rb +29 -0
  48. data/lib/chef/provider/user/mac.rb +1 -1
  49. data/lib/chef/provider/user/windows.rb +2 -2
  50. data/lib/chef/provider/user.rb +45 -9
  51. data/lib/chef/provider.rb +1 -1
  52. data/lib/chef/recipe.rb +1 -1
  53. data/lib/chef/resource/_rest_resource.rb +389 -0
  54. data/lib/chef/resource/alternatives.rb +0 -1
  55. data/lib/chef/resource/apt_package.rb +0 -1
  56. data/lib/chef/resource/apt_preference.rb +0 -1
  57. data/lib/chef/resource/apt_repository.rb +0 -1
  58. data/lib/chef/resource/apt_update.rb +0 -1
  59. data/lib/chef/resource/archive_file.rb +0 -1
  60. data/lib/chef/resource/bash.rb +0 -1
  61. data/lib/chef/resource/batch.rb +0 -1
  62. data/lib/chef/resource/bff_package.rb +0 -1
  63. data/lib/chef/resource/breakpoint.rb +0 -1
  64. data/lib/chef/resource/build_essential.rb +0 -1
  65. data/lib/chef/resource/cab_package.rb +0 -1
  66. data/lib/chef/resource/chef_client_config.rb +17 -14
  67. data/lib/chef/resource/chef_client_cron.rb +1 -2
  68. data/lib/chef/resource/chef_client_launchd.rb +2 -2
  69. data/lib/chef/resource/chef_client_scheduled_task.rb +3 -3
  70. data/lib/chef/resource/chef_client_systemd_timer.rb +0 -1
  71. data/lib/chef/resource/chef_client_trusted_certificate.rb +0 -1
  72. data/lib/chef/resource/chef_gem.rb +0 -1
  73. data/lib/chef/resource/chef_handler.rb +0 -1
  74. data/lib/chef/resource/chef_sleep.rb +1 -3
  75. data/lib/chef/resource/chef_vault_secret.rb +0 -1
  76. data/lib/chef/resource/chocolatey_config.rb +0 -1
  77. data/lib/chef/resource/chocolatey_feature.rb +0 -1
  78. data/lib/chef/resource/chocolatey_package.rb +0 -1
  79. data/lib/chef/resource/chocolatey_source.rb +0 -1
  80. data/lib/chef/resource/cookbook_file.rb +0 -1
  81. data/lib/chef/resource/cron/_cron_shared.rb +0 -1
  82. data/lib/chef/resource/cron/cron.rb +0 -1
  83. data/lib/chef/resource/cron/cron_d.rb +15 -1
  84. data/lib/chef/resource/cron_access.rb +0 -1
  85. data/lib/chef/resource/csh.rb +0 -1
  86. data/lib/chef/resource/directory.rb +0 -1
  87. data/lib/chef/resource/dmg_package.rb +0 -1
  88. data/lib/chef/resource/dnf_package.rb +0 -1
  89. data/lib/chef/resource/dpkg_package.rb +0 -1
  90. data/lib/chef/resource/dsc_resource.rb +0 -1
  91. data/lib/chef/resource/dsc_script.rb +0 -1
  92. data/lib/chef/resource/execute.rb +0 -1
  93. data/lib/chef/resource/file.rb +0 -1
  94. data/lib/chef/resource/freebsd_package.rb +0 -1
  95. data/lib/chef/resource/gem_package.rb +0 -1
  96. data/lib/chef/resource/group.rb +25 -2
  97. data/lib/chef/resource/habitat/habitat_package.rb +0 -1
  98. data/lib/chef/resource/habitat/habitat_sup.rb +6 -7
  99. data/lib/chef/resource/habitat/habitat_sup_windows.rb +1 -1
  100. data/lib/chef/resource/habitat_config.rb +0 -1
  101. data/lib/chef/resource/habitat_install.rb +0 -1
  102. data/lib/chef/resource/habitat_service.rb +0 -1
  103. data/lib/chef/resource/habitat_user_toml.rb +0 -1
  104. data/lib/chef/resource/homebrew_cask.rb +0 -1
  105. data/lib/chef/resource/homebrew_package.rb +0 -1
  106. data/lib/chef/resource/homebrew_tap.rb +0 -1
  107. data/lib/chef/resource/homebrew_update.rb +0 -2
  108. data/lib/chef/resource/hostname.rb +0 -1
  109. data/lib/chef/resource/http_request.rb +0 -1
  110. data/lib/chef/resource/ifconfig.rb +0 -1
  111. data/lib/chef/resource/inspec_input.rb +0 -1
  112. data/lib/chef/resource/inspec_waiver.rb +0 -1
  113. data/lib/chef/resource/inspec_waiver_file_entry.rb +2 -3
  114. data/lib/chef/resource/ips_package.rb +0 -1
  115. data/lib/chef/resource/kernel_module.rb +0 -1
  116. data/lib/chef/resource/ksh.rb +0 -1
  117. data/lib/chef/resource/launchd.rb +0 -1
  118. data/lib/chef/resource/link.rb +0 -1
  119. data/lib/chef/resource/locale.rb +1 -2
  120. data/lib/chef/resource/log.rb +0 -1
  121. data/lib/chef/resource/lwrp_base.rb +0 -4
  122. data/lib/chef/resource/macos_userdefaults.rb +0 -1
  123. data/lib/chef/resource/macosx_service.rb +0 -1
  124. data/lib/chef/resource/macports_package.rb +0 -1
  125. data/lib/chef/resource/mdadm.rb +0 -1
  126. data/lib/chef/resource/mount.rb +0 -1
  127. data/lib/chef/resource/msu_package.rb +0 -1
  128. data/lib/chef/resource/notify_group.rb +0 -2
  129. data/lib/chef/resource/ohai.rb +0 -1
  130. data/lib/chef/resource/ohai_hint.rb +0 -1
  131. data/lib/chef/resource/openbsd_package.rb +0 -1
  132. data/lib/chef/resource/openssl_dhparam.rb +0 -2
  133. data/lib/chef/resource/openssl_ec_private_key.rb +0 -2
  134. data/lib/chef/resource/openssl_ec_public_key.rb +0 -2
  135. data/lib/chef/resource/openssl_rsa_private_key.rb +0 -2
  136. data/lib/chef/resource/openssl_rsa_public_key.rb +0 -2
  137. data/lib/chef/resource/openssl_x509_certificate.rb +0 -2
  138. data/lib/chef/resource/openssl_x509_crl.rb +0 -2
  139. data/lib/chef/resource/openssl_x509_request.rb +0 -2
  140. data/lib/chef/resource/osx_profile.rb +0 -1
  141. data/lib/chef/resource/package.rb +0 -1
  142. data/lib/chef/resource/pacman_package.rb +0 -1
  143. data/lib/chef/resource/paludis_package.rb +0 -1
  144. data/lib/chef/resource/perl.rb +0 -1
  145. data/lib/chef/resource/plist.rb +7 -3
  146. data/lib/chef/resource/portage_package.rb +0 -1
  147. data/lib/chef/resource/powershell_package.rb +0 -1
  148. data/lib/chef/resource/powershell_package_source.rb +0 -1
  149. data/lib/chef/resource/powershell_script.rb +0 -1
  150. data/lib/chef/resource/python.rb +0 -1
  151. data/lib/chef/resource/reboot.rb +0 -1
  152. data/lib/chef/resource/registry_key.rb +0 -1
  153. data/lib/chef/resource/remote_directory.rb +0 -1
  154. data/lib/chef/resource/remote_file.rb +0 -1
  155. data/lib/chef/resource/rhsm_errata.rb +0 -1
  156. data/lib/chef/resource/rhsm_errata_level.rb +0 -1
  157. data/lib/chef/resource/rhsm_register.rb +17 -1
  158. data/lib/chef/resource/rhsm_repo.rb +0 -1
  159. data/lib/chef/resource/rhsm_subscription.rb +0 -1
  160. data/lib/chef/resource/route.rb +0 -1
  161. data/lib/chef/resource/rpm_package.rb +0 -1
  162. data/lib/chef/resource/ruby.rb +0 -1
  163. data/lib/chef/resource/ruby_block.rb +0 -1
  164. data/lib/chef/resource/scm/_scm.rb +0 -2
  165. data/lib/chef/resource/scm/git.rb +0 -2
  166. data/lib/chef/resource/scm/subversion.rb +0 -2
  167. data/lib/chef/resource/script.rb +0 -1
  168. data/lib/chef/resource/selinux/common_helpers.rb +47 -0
  169. data/lib/chef/resource/selinux/selinux_debian.erb +18 -0
  170. data/lib/chef/resource/selinux/selinux_default.erb +15 -0
  171. data/lib/chef/resource/selinux_boolean.rb +101 -0
  172. data/lib/chef/resource/selinux_fcontext.rb +160 -0
  173. data/lib/chef/resource/selinux_install.rb +107 -0
  174. data/lib/chef/resource/selinux_module.rb +143 -0
  175. data/lib/chef/resource/selinux_permissive.rb +64 -0
  176. data/lib/chef/resource/selinux_port.rb +118 -0
  177. data/lib/chef/resource/selinux_state.rb +166 -0
  178. data/lib/chef/resource/service.rb +0 -1
  179. data/lib/chef/resource/smartos_package.rb +0 -1
  180. data/lib/chef/resource/snap_package.rb +0 -1
  181. data/lib/chef/resource/solaris_package.rb +0 -1
  182. data/lib/chef/resource/ssh_known_hosts_entry.rb +0 -1
  183. data/lib/chef/resource/sudo.rb +0 -1
  184. data/lib/chef/resource/support/client.erb +3 -4
  185. data/lib/chef/resource/swap_file.rb +0 -1
  186. data/lib/chef/resource/sysctl.rb +1 -2
  187. data/lib/chef/resource/systemd_unit.rb +0 -1
  188. data/lib/chef/resource/template.rb +0 -1
  189. data/lib/chef/resource/timezone.rb +0 -1
  190. data/lib/chef/resource/user/aix_user.rb +0 -1
  191. data/lib/chef/resource/user/linux_user.rb +0 -1
  192. data/lib/chef/resource/user/mac_user.rb +0 -1
  193. data/lib/chef/resource/user/pw_user.rb +0 -1
  194. data/lib/chef/resource/user/solaris_user.rb +0 -1
  195. data/lib/chef/resource/user/windows_user.rb +0 -1
  196. data/lib/chef/resource/user.rb +10 -1
  197. data/lib/chef/resource/user_ulimit.rb +0 -1
  198. data/lib/chef/resource/whyrun_safe_ruby_block.rb +0 -1
  199. data/lib/chef/resource/windows_ad_join.rb +0 -2
  200. data/lib/chef/resource/windows_audit_policy.rb +0 -2
  201. data/lib/chef/resource/windows_auto_run.rb +0 -1
  202. data/lib/chef/resource/windows_certificate.rb +54 -43
  203. data/lib/chef/resource/windows_defender.rb +0 -1
  204. data/lib/chef/resource/windows_defender_exclusion.rb +0 -1
  205. data/lib/chef/resource/windows_dfs_folder.rb +0 -1
  206. data/lib/chef/resource/windows_dfs_namespace.rb +0 -1
  207. data/lib/chef/resource/windows_dfs_server.rb +0 -1
  208. data/lib/chef/resource/windows_dns_record.rb +0 -1
  209. data/lib/chef/resource/windows_dns_zone.rb +0 -1
  210. data/lib/chef/resource/windows_env.rb +0 -1
  211. data/lib/chef/resource/windows_feature.rb +0 -1
  212. data/lib/chef/resource/windows_feature_dism.rb +0 -1
  213. data/lib/chef/resource/windows_feature_powershell.rb +0 -1
  214. data/lib/chef/resource/windows_firewall_profile.rb +0 -2
  215. data/lib/chef/resource/windows_firewall_rule.rb +0 -1
  216. data/lib/chef/resource/windows_font.rb +2 -3
  217. data/lib/chef/resource/windows_package.rb +0 -1
  218. data/lib/chef/resource/windows_pagefile.rb +27 -22
  219. data/lib/chef/resource/windows_path.rb +0 -1
  220. data/lib/chef/resource/windows_printer.rb +0 -1
  221. data/lib/chef/resource/windows_printer_port.rb +0 -1
  222. data/lib/chef/resource/windows_script.rb +0 -2
  223. data/lib/chef/resource/windows_security_policy.rb +0 -1
  224. data/lib/chef/resource/windows_service.rb +0 -1
  225. data/lib/chef/resource/windows_share.rb +0 -1
  226. data/lib/chef/resource/windows_shortcut.rb +1 -2
  227. data/lib/chef/resource/windows_task.rb +0 -1
  228. data/lib/chef/resource/windows_uac.rb +0 -1
  229. data/lib/chef/resource/windows_update_settings.rb +0 -1
  230. data/lib/chef/resource/windows_user_privilege.rb +36 -27
  231. data/lib/chef/resource/windows_workgroup.rb +0 -1
  232. data/lib/chef/resource/yum_package.rb +0 -1
  233. data/lib/chef/resource/yum_repository.rb +0 -1
  234. data/lib/chef/resource/zypper_package.rb +0 -1
  235. data/lib/chef/resource/zypper_repository.rb +0 -1
  236. data/lib/chef/resource.rb +13 -5
  237. data/lib/chef/resources.rb +7 -0
  238. data/lib/chef/run_context.rb +19 -3
  239. data/lib/chef/secret_fetcher/azure_key_vault.rb +3 -3
  240. data/lib/chef/secret_fetcher/hashi_vault.rb +1 -1
  241. data/lib/chef/version.rb +1 -1
  242. data/lib/chef/win32/handle.rb +6 -7
  243. data/lib/chef/win32/registry.rb +7 -3
  244. data/lib/chef/win32/version.rb +2 -1
  245. data/spec/data/rubygems.org/sexp_processor-info +2 -1
  246. data/spec/functional/resource/dnf_package_spec.rb +15 -0
  247. data/spec/functional/resource/dsc_script_spec.rb +1 -1
  248. data/spec/functional/resource/group_spec.rb +10 -6
  249. data/spec/functional/resource/link_spec.rb +8 -8
  250. data/spec/functional/resource/plist_spec.rb +25 -0
  251. data/spec/functional/resource/user/linux_user_spec.rb +127 -0
  252. data/spec/functional/resource/windows_certificate_spec.rb +15 -12
  253. data/spec/functional/resource/windows_font_spec.rb +11 -8
  254. data/spec/functional/resource/windows_pagefile_spec.rb +31 -4
  255. data/spec/functional/resource/yum_package_spec.rb +15 -0
  256. data/spec/functional/resource/zypper_package_spec.rb +12 -0
  257. data/spec/functional/shell_spec.rb +7 -2
  258. data/spec/functional/version_spec.rb +1 -1
  259. data/spec/integration/client/client_spec.rb +82 -3
  260. data/spec/integration/client/exit_code_spec.rb +1 -1
  261. data/spec/integration/client/ipv6_spec.rb +1 -1
  262. data/spec/integration/compliance/compliance_spec.rb +1 -1
  263. data/spec/integration/recipes/accumulator_spec.rb +1 -1
  264. data/spec/integration/recipes/lwrp_inline_resources_spec.rb +1 -1
  265. data/spec/integration/recipes/lwrp_spec.rb +1 -1
  266. data/spec/integration/recipes/notifies_spec.rb +1 -1
  267. data/spec/integration/recipes/notifying_block_spec.rb +1 -1
  268. data/spec/integration/recipes/remote_directory.rb +1 -1
  269. data/spec/integration/recipes/unified_mode_spec.rb +1 -1
  270. data/spec/integration/recipes/use_partial_spec.rb +2 -1
  271. data/spec/integration/solo/solo_spec.rb +2 -2
  272. data/spec/spec_helper.rb +1 -0
  273. data/spec/support/platform_helpers.rb +4 -0
  274. data/spec/support/ruby_installer.rb +1 -1
  275. data/spec/support/shared/functional/windows_script.rb +2 -2
  276. data/spec/unit/application/client_spec.rb +0 -10
  277. data/spec/unit/client_spec.rb +54 -2
  278. data/spec/unit/cookbook/syntax_check_spec.rb +3 -0
  279. data/spec/unit/daemon_spec.rb +1 -5
  280. data/spec/unit/dsl/secret_spec.rb +127 -23
  281. data/spec/unit/http/authenticator_spec.rb +68 -0
  282. data/spec/unit/mixin/powershell_exec_spec.rb +5 -5
  283. data/spec/unit/platform/query_helpers_spec.rb +2 -17
  284. data/spec/unit/provider/http_request_spec.rb +60 -72
  285. data/spec/unit/provider/mount/linux_spec.rb +10 -0
  286. data/spec/unit/provider/package/rubygems_spec.rb +2 -2
  287. data/spec/unit/provider/package/zypper_spec.rb +32 -0
  288. data/spec/unit/provider/user/linux_spec.rb +96 -1
  289. data/spec/unit/provider/user_spec.rb +24 -6
  290. data/spec/unit/resource/archive_file_spec.rb +1 -1
  291. data/spec/unit/resource/chef_client_config_spec.rb +8 -0
  292. data/spec/unit/resource/chef_client_cron_spec.rb +5 -0
  293. data/spec/unit/resource/chef_client_launchd_spec.rb +5 -0
  294. data/spec/unit/resource/chef_client_scheduled_task_spec.rb +5 -0
  295. data/spec/unit/resource/chef_client_systemd_timer_spec.rb +1 -1
  296. data/spec/unit/resource/cron_d_spec.rb +37 -1
  297. data/spec/unit/resource/rest_resource_spec.rb +381 -0
  298. data/spec/unit/resource/selinux_boolean_spec.rb +92 -0
  299. data/spec/unit/resource/selinux_fcontext_spec.rb +65 -0
  300. data/spec/unit/resource/selinux_install_spec.rb +60 -0
  301. data/spec/unit/resource/selinux_module_spec.rb +55 -0
  302. data/spec/unit/resource/selinux_permissive_spec.rb +39 -0
  303. data/spec/unit/resource/selinux_port_spec.rb +42 -0
  304. data/spec/unit/resource/selinux_state_spec.rb +46 -0
  305. data/spec/unit/resource/sysctl_spec.rb +2 -2
  306. data/spec/unit/resource/user/linux_user_spec.rb +42 -0
  307. data/spec/unit/resource_spec.rb +21 -1
  308. data/spec/unit/run_context_spec.rb +16 -0
  309. data/spec/unit/util/dsc/local_configuration_manager_spec.rb +1 -1
  310. data/tasks/rspec.rb +1 -1
  311. metadata +93 -21
@@ -0,0 +1,77 @@
1
+ #
2
+ # Copyright:: Copyright 2008-2016, Chef, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require "chef/constants" unless defined?(NOT_PASSED)
19
+
20
+ class Chef
21
+ module DSL
22
+ module RestResource
23
+ def rest_property_map(rest_property_map = NOT_PASSED)
24
+ if rest_property_map != NOT_PASSED
25
+ rest_property_map = rest_property_map.to_h { |k| [k.to_sym, k] } if rest_property_map.is_a? Array
26
+
27
+ @rest_property_map = rest_property_map
28
+ end
29
+ @rest_property_map
30
+ end
31
+
32
+ # URL to collection
33
+ def rest_api_collection(rest_api_collection = NOT_PASSED)
34
+ if rest_api_collection != NOT_PASSED
35
+ raise ArgumentError, "You must pass an absolute path to rest_api_collection" unless rest_api_collection.start_with? "/"
36
+
37
+ @rest_api_collection = rest_api_collection
38
+ end
39
+
40
+ @rest_api_collection
41
+ end
42
+
43
+ # RFC6570-Templated URL to document
44
+ def rest_api_document(rest_api_document = NOT_PASSED, first_element_only: false)
45
+ if rest_api_document != NOT_PASSED
46
+ raise ArgumentError, "You must pass an absolute path to rest_api_document" unless rest_api_document.start_with? "/"
47
+
48
+ @rest_api_document = rest_api_document
49
+ @rest_api_document_first_element_only = first_element_only
50
+ end
51
+ @rest_api_document
52
+ end
53
+
54
+ # Explicit REST document identity mapping
55
+ def rest_identity_map(rest_identity_map = NOT_PASSED)
56
+ @rest_identity_map = rest_identity_map if rest_identity_map != NOT_PASSED
57
+ @rest_identity_map
58
+ end
59
+
60
+ # Mark up properties for POST only, not PATCH/PUT
61
+ def rest_post_only_properties(rest_post_only_properties = NOT_PASSED)
62
+ if rest_post_only_properties != NOT_PASSED
63
+ @rest_post_only_properties = Array(rest_post_only_properties).map(&:to_sym)
64
+ end
65
+ @rest_post_only_properties || []
66
+ end
67
+
68
+ def rest_api_document_first_element_only(rest_api_document_first_element_only = NOT_PASSED)
69
+ if rest_api_document_first_element_only != NOT_PASSED
70
+ @rest_api_document_first_element_only = rest_api_document_first_element_only
71
+ end
72
+ @rest_api_document_first_element_only
73
+ end
74
+
75
+ end
76
+ end
77
+ end
@@ -21,6 +21,118 @@ class Chef
21
21
  module DSL
22
22
  module Secret
23
23
 
24
+ #
25
+ # This allows you to set the default secret service that is used when
26
+ # fetching secrets.
27
+ #
28
+ # @example
29
+ #
30
+ # default_secret_service :hashi_vault
31
+ # val1 = secret(name: "test1", config: { region: "us-west-1" })
32
+ #
33
+ # @example
34
+ #
35
+ # default_secret_service #=> nil
36
+ # default_secret_service :hashi_vault
37
+ # default_secret_service #=> :hashi_vault
38
+ #
39
+ # @param [Symbol] service default secret service to use when fetching secrets
40
+ # @return [Symbol, nil] default secret service to use when fetching secrets
41
+ #
42
+ def default_secret_service(service = nil)
43
+ return run_context.default_secret_service if service.nil?
44
+ raise Chef::Exceptions::Secret::InvalidFetcherService.new("Unsupported secret service: #{service.inspect}", Chef::SecretFetcher::SECRET_FETCHERS) unless Chef::SecretFetcher::SECRET_FETCHERS.include?(service)
45
+
46
+ run_context.default_secret_service = service
47
+ end
48
+
49
+ #
50
+ # This allows you to set the secret service for the scope of the block
51
+ # passed into this method.
52
+ #
53
+ # @example
54
+ #
55
+ # with_secret_service :hashi_vault do
56
+ # val1 = secret(name: "test1", config: { region: "us-west-1" })
57
+ # val2 = secret(name: "test2", config: { region: "us-west-1" })
58
+ # end
59
+ #
60
+ # @example Combine with #with_secret_config
61
+ #
62
+ # with_secret_service :hashi_vault do
63
+ # with_secret_config region: "us-west-1" do
64
+ # val1 = secret(name: "test1")
65
+ # val2 = secret(name: "test2")
66
+ # end
67
+ # end
68
+ #
69
+ # @param [Symbol] service The default secret service to use when fetching secrets
70
+ #
71
+ def with_secret_service(service)
72
+ raise ArgumentError, "You must pass a block to #with_secret_service" unless block_given?
73
+
74
+ begin
75
+ old_service = default_secret_service
76
+ # Use "public" API for input validation
77
+ default_secret_service(service)
78
+ yield
79
+ ensure
80
+ # Use "private" API so we can set back to nil
81
+ run_context.default_secret_service = old_service
82
+ end
83
+ end
84
+
85
+ #
86
+ # This allows you to set the default secret config that is used when
87
+ # fetching secrets.
88
+ #
89
+ # @example
90
+ #
91
+ # default_secret_config region: "us-west-1"
92
+ # val1 = secret(name: "test1", service: :hashi_vault)
93
+ #
94
+ # @example
95
+ #
96
+ # default_secret_config #=> {}
97
+ # default_secret_service region: "us-west-1"
98
+ # default_secret_service #=> { region: "us-west-1" }
99
+ #
100
+ # @param [Hash<Symbol,Object>] config The default configuration options to apply when fetching secrets
101
+ # @return [Hash<Symbol,Object>]
102
+ #
103
+ def default_secret_config(**config)
104
+ return run_context.default_secret_config if config.empty?
105
+
106
+ run_context.default_secret_config = config
107
+ end
108
+
109
+ #
110
+ # This allows you to set the secret config for the scope of the block
111
+ # passed into this method.
112
+ #
113
+ # @example
114
+ #
115
+ # with_secret_config region: "us-west-1" do
116
+ # val1 = secret(name: "test1", service: :hashi_vault)
117
+ # val2 = secret(name: "test2", service: :hashi_vault)
118
+ # end
119
+ #
120
+ # @param [Hash<Symbol,Object>] config The default configuration options to use when fetching secrets
121
+ #
122
+ def with_secret_config(**config)
123
+ raise ArgumentError, "You must pass a block to #with_secret_config" unless block_given?
124
+
125
+ begin
126
+ old_config = default_secret_config
127
+ # Use "public" API for input validation
128
+ default_secret_config(**config)
129
+ yield
130
+ ensure
131
+ # Use "private" API so we can set back to nil
132
+ run_context.default_secret_config = old_config
133
+ end
134
+ end
135
+
24
136
  # Helper method which looks up a secret using the given service and configuration,
25
137
  # and returns the retrieved secret value.
26
138
  # This DSL providers a wrapper around [Chef::SecretFetcher]
@@ -49,11 +161,7 @@ class Chef
49
161
  #
50
162
  # value = secret(name: "test1", service: :aws_secrets_manager, version: "v1", config: { region: "us-west-1" })
51
163
  # log "My secret is #{value}"
52
- def secret(name: nil, version: nil, service: nil, config: {})
53
- Chef::Log.warn <<~EOM.gsub("\n", " ")
54
- The secrets Chef Infra language helper is currently in beta. If you have feedback or you would
55
- like to be part of the future design of this helper e-mail us at secrets_management_beta@progress.com"
56
- EOM
164
+ def secret(name: nil, version: nil, service: default_secret_service, config: default_secret_config)
57
165
  sensitive(true) if is_a?(Chef::Resource)
58
166
  Chef::SecretFetcher.for_service(service, config, run_context).fetch(name, version)
59
167
  end
@@ -273,6 +273,9 @@ class Chef
273
273
  # Called if the converge phase fails
274
274
  def converge_failed(exception); end
275
275
 
276
+ # Called when migrating from a pem on disk to a pem stored in Keychain or Windows Certstore
277
+ def key_migration_status(key_migrated = false); end
278
+
276
279
  # TODO: need events for notification resolve?
277
280
  # def notifications_resolved
278
281
  # end
@@ -561,5 +561,13 @@ class Chef
561
561
  super "before subscription from #{notification.resource} resource cannot be setup to #{notification.notifying_resource} resource, which has already fired while in unified mode"
562
562
  end
563
563
  end
564
+
565
+ class RestError < RuntimeError; end
566
+
567
+ class RestTargetError < RestError; end
568
+
569
+ class RestTimeout < RestError; end
570
+
571
+ class RestOperationFailed < RestError; end
564
572
  end
565
573
  end
@@ -16,16 +16,19 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
+ require "chef/mixin/powershell_exec"
19
20
  require_relative "auth_credentials"
20
21
  require_relative "../exceptions"
22
+ require_relative "../win32/registry"
21
23
  autoload :OpenSSL, "openssl"
22
24
 
23
25
  class Chef
24
26
  class HTTP
25
27
  class Authenticator
26
-
27
28
  DEFAULT_SERVER_API_VERSION = "2".freeze
28
29
 
30
+ extend Chef::Mixin::PowershellExec
31
+
29
32
  attr_reader :signing_key_filename
30
33
  attr_reader :raw_key
31
34
  attr_reader :attr_names
@@ -83,13 +86,69 @@ class Chef
83
86
  @auth_credentials.client_name
84
87
  end
85
88
 
89
+ def detect_certificate_key(client_name)
90
+ self.class.detect_certificate_key(client_name)
91
+ end
92
+
93
+ def check_certstore_for_key(client_name)
94
+ self.class.check_certstore_for_key(client_name)
95
+ end
96
+
97
+ def retrieve_certificate_key(client_name)
98
+ self.class.retrieve_certificate_key(client_name)
99
+ end
100
+
101
+ def get_cert_password
102
+ self.class.get_cert_password
103
+ end
104
+
105
+ def encrypt_pfx_pass
106
+ self.class.encrypt_pfx_pass
107
+ end
108
+
109
+ def decrypt_pfx_pass
110
+ self.class.decrypt_pfx_pass
111
+ end
112
+
113
+ # Detects if a private key exists in a certificate repository like Keychain (macOS) or Certificate Store (Windows)
114
+ #
115
+ # @param client_name - we're using the node name to store and retrieve any keys
116
+ # Returns true if a key is found, false if not. False will trigger a registration event which will lead to a certificate based key being created
117
+ #
118
+ def self.detect_certificate_key(client_name)
119
+ if ChefUtils.windows?
120
+ check_certstore_for_key(client_name)
121
+ else # generic return for Mac and LInux clients
122
+ false
123
+ end
124
+ end
125
+
126
+ def self.check_certstore_for_key(client_name)
127
+ powershell_code = <<~CODE
128
+ $cert = Get-ChildItem -path cert:\\LocalMachine\\My -Recurse -Force | Where-Object { $_.Subject -Match "chef-#{client_name}" } -ErrorAction Stop
129
+ if (($cert.HasPrivateKey -eq $true) -and ($cert.PrivateKey.Key.ExportPolicy -ne "NonExportable")) {
130
+ return $true
131
+ }
132
+ else{
133
+ return $false
134
+ }
135
+ CODE
136
+ powershell_exec!(powershell_code).result
137
+ end
138
+
86
139
  def load_signing_key(key_file, raw_key = nil)
87
- if !!key_file
140
+ results = retrieve_certificate_key(Chef::Config[:node_name])
141
+
142
+ if !!results
143
+ @raw_key = results
144
+ elsif key_file == nil? && raw_key == nil?
145
+ puts "\nNo key detected\n"
146
+ elsif !!key_file
88
147
  @raw_key = IO.read(key_file).strip
89
148
  elsif !!raw_key
90
149
  @raw_key = raw_key.strip
91
150
  else
92
- return nil
151
+ return
93
152
  end
94
153
  # Pass in '' as the passphrase to avoid OpenSSL prompting on the TTY if
95
154
  # given an encrypted key. This also helps if using a single file for
@@ -104,6 +163,114 @@ class Chef
104
163
  raise Chef::Exceptions::InvalidPrivateKey, msg
105
164
  end
106
165
 
166
+ def self.get_cert_password
167
+ @win32registry = Chef::Win32::Registry.new
168
+ path = "HKEY_LOCAL_MACHINE\\Software\\Progress\\Authentication"
169
+ # does the registry key even exist?
170
+ present = @win32registry.get_values(path)
171
+ if present.nil? || present.empty?
172
+ raise Chef::Exceptions::Win32RegKeyMissing
173
+ end
174
+
175
+ present.each do |secret|
176
+ if secret[:name] == "PfxPass"
177
+ password = decrypt_pfx_pass(secret[:data])
178
+ return password
179
+ end
180
+ end
181
+
182
+ raise Chef::Exceptions::Win32RegKeyMissing
183
+
184
+ rescue Chef::Exceptions::Win32RegKeyMissing
185
+ # if we don't have a password, log that and generate one
186
+ Chef::Log.warn "Authentication Hive and values not present in registry, creating them now"
187
+ new_path = "HKEY_LOCAL_MACHINE\\Software\\Progress\\Authentication"
188
+ unless @win32registry.key_exists?(new_path)
189
+ @win32registry.create_key(new_path, true)
190
+ end
191
+ require "securerandom" unless defined?(SecureRandom)
192
+ size = 14
193
+ password = SecureRandom.alphanumeric(size)
194
+ encrypted_pass = encrypt_pfx_pass(password)
195
+ values = { name: "PfxPass", type: :string, data: encrypted_pass }
196
+ @win32registry.set_value(new_path, values)
197
+ password
198
+ end
199
+
200
+ def self.encrypt_pfx_pass(password)
201
+ powershell_code = <<~CODE
202
+ $encrypted_string = ConvertTo-SecureString "#{password}" -AsPlainText -Force
203
+ $secure_string = ConvertFrom-SecureString $encrypted_string
204
+ return $secure_string
205
+ CODE
206
+ powershell_exec!(powershell_code).result
207
+ end
208
+
209
+ def self.decrypt_pfx_pass(password)
210
+ powershell_code = <<~CODE
211
+ $secure_string = "#{password}" | ConvertTo-SecureString
212
+ $string = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((($secure_string))))
213
+ return $string
214
+ CODE
215
+ powershell_exec!(powershell_code).result
216
+ end
217
+
218
+ def self.retrieve_certificate_key(client_name)
219
+ require "openssl" unless defined?(OpenSSL)
220
+
221
+ if ChefUtils.windows?
222
+ password = get_cert_password
223
+ return false unless password
224
+
225
+ if check_certstore_for_key(client_name)
226
+ ps_blob = powershell_exec!(get_the_key_ps(client_name, password)).result
227
+ file_path = ps_blob["PSPath"].split("::")[1]
228
+ pkcs = OpenSSL::PKCS12.new(File.binread(file_path), password)
229
+
230
+ # We check the pfx we just extracted the private key from
231
+ # if that cert is expiring in 7 days or less we generate a new pfx/p12 object
232
+ # then we post the new public key from that to the client endpoint on
233
+ # chef server.
234
+ File.delete(file_path)
235
+ key_expiring = is_certificate_expiring?(pkcs)
236
+ if key_expiring
237
+ powershell_exec!(delete_old_key_ps(client_name))
238
+ ::Chef::Client.update_key_and_register(Chef::Config[:client_name], pkcs)
239
+ end
240
+
241
+ return pkcs.key.private_to_pem
242
+ end
243
+ end
244
+
245
+ false
246
+ end
247
+
248
+ def self.is_certificate_expiring?(pkcs)
249
+ today = Date.parse(Time.now.utc.iso8601)
250
+ future = Date.parse(pkcs.certificate.not_after.iso8601)
251
+ future.mjd - today.mjd <= 7
252
+ end
253
+
254
+ def self.get_the_key_ps(client_name, password)
255
+ powershell_code = <<~CODE
256
+ Try {
257
+ $my_pwd = ConvertTo-SecureString -String "#{password}" -Force -AsPlainText;
258
+ $cert = Get-ChildItem -path cert:\\LocalMachine\\My -Recurse | Where-Object { $_.Subject -match "chef-#{client_name}$" } -ErrorAction Stop;
259
+ $tempfile = [System.IO.Path]::GetTempPath() + "export_pfx.pfx";
260
+ Export-PfxCertificate -Cert $cert -Password $my_pwd -FilePath $tempfile;
261
+ }
262
+ Catch {
263
+ return $false
264
+ }
265
+ CODE
266
+ end
267
+
268
+ def self.delete_old_key_ps(client_name)
269
+ powershell_code = <<~CODE
270
+ Get-ChildItem -path cert:\\LocalMachine\\My -Recurse | Where-Object { $_.Subject -match "chef-#{client_name}$" } | Remove-Item -ErrorAction Stop;
271
+ CODE
272
+ end
273
+
107
274
  def authentication_headers(method, url, json_body = nil, headers = nil)
108
275
  request_params = {
109
276
  http_method: method,
@@ -88,10 +88,10 @@ class Chef
88
88
  certs = Dir.glob(::File.join(Chef::Util::PathHelper.escape_glob_dir(config.trusted_certs_dir), "*.{crt,pem}"))
89
89
  certs.each do |cert_file|
90
90
  cert = begin
91
- OpenSSL::X509::Certificate.new(::File.binread(cert_file))
91
+ OpenSSL::X509::Certificate.new(::File.binread(cert_file))
92
92
  rescue OpenSSL::X509::CertificateError => e
93
93
  raise Chef::Exceptions::ConfigurationError, "Error reading cert file '#{cert_file}', original error '#{e.class}: #{e.message}'"
94
- end
94
+ end
95
95
  add_trusted_cert(cert)
96
96
  end
97
97
  end
@@ -132,7 +132,7 @@ class Chef
132
132
  def add_trusted_cert(cert)
133
133
  http_client.cert_store.add_cert(cert)
134
134
  rescue OpenSSL::X509::StoreError => e
135
- raise e unless e.message == "cert already in hash table"
135
+ raise e unless e.message =~ /cert already in hash table/
136
136
  end
137
137
 
138
138
  end
@@ -15,9 +15,6 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
- require_relative "../powershell"
19
- require_relative "../pwsh"
20
-
21
18
  # The powershell_exec mixin provides in-process access to the PowerShell engine.
22
19
  #
23
20
  # powershell_exec is initialized with a string that should be set to the script
@@ -94,35 +91,15 @@ require_relative "../pwsh"
94
91
  # - It is not possible to impersonate another user running powershell, the
95
92
  # credentials of the user running Chef Client are used.
96
93
  #
94
+ if ChefUtils.windows?
95
+ require "chef-powershell"
96
+ end
97
97
 
98
98
  class Chef
99
99
  module Mixin
100
100
  module PowershellExec
101
- # Run a command under PowerShell via a managed (.NET) API.
102
- #
103
- # Requires: .NET Framework 4.0 or higher on the target machine.
104
- #
105
- # @param script [String] script to run
106
- # @param interpreter [Symbol] the interpreter type, `:powershell` or `:pwsh`
107
- # @param timeout [Integer, nil] timeout in seconds.
108
- # @return [Chef::PowerShell] output
109
- def powershell_exec(script, interpreter = :powershell, timeout: -1)
110
- case interpreter
111
- when :powershell
112
- Chef::PowerShell.new(script, timeout: timeout)
113
- when :pwsh
114
- Chef::Pwsh.new(script, timeout: timeout)
115
- else
116
- raise ArgumentError, "Expected interpreter of :powershell or :pwsh"
117
- end
118
- end
119
-
120
- # The same as the #powershell_exec method except this will raise
121
- # Chef::PowerShell::CommandFailed if the command fails
122
- def powershell_exec!(script, interpreter = :powershell, **options)
123
- cmd = powershell_exec(script, interpreter, **options)
124
- cmd.error!
125
- cmd
101
+ if ChefUtils.windows?
102
+ include ChefPowerShell::ChefPowerShellModule::PowerShellExec
126
103
  end
127
104
  end
128
105
  end
@@ -274,6 +274,12 @@ class Chef
274
274
  result
275
275
  end
276
276
 
277
+ # This method returns list of sensitive properties
278
+ # @return [Array<Property>] All sensitive properties.
279
+ def sensitive_properties
280
+ properties.values.empty? ? [] : properties.values.select(&:sensitive?)
281
+ end
282
+
277
283
  # Returns the name of the name property. Returns nil if there is no name property.
278
284
  #
279
285
  # @return [Symbol] the name property for this resource
@@ -452,17 +452,34 @@ class Chef
452
452
  # method-style access to attributes (has to come after the prepended ImmutablizeHash)
453
453
 
454
454
  def read(*path)
455
- merged_attributes.read(*path)
455
+ if path[0].nil?
456
+ Chef::Log.warn "Calling node.read() without any path argument is very slow, probably a bug, and should be avoided"
457
+ merged_attributes.read(*path) # re-merges everything, slow edge case
458
+ else
459
+ self[path[0]] unless path[0].nil? # force deep_merge_cache key construction if necessary
460
+ deep_merge_cache.read(*path)
461
+ end
456
462
  end
457
463
 
458
464
  alias :dig :read
459
465
 
460
466
  def read!(*path)
461
- merged_attributes.read!(*path)
467
+ if path[0].nil?
468
+ Chef::Log.warn "Calling node.read!() without any path argument is very slow, probably a bug, and should be avoided"
469
+ merged_attributes.read!(*path) # re-merges everything, slow edge case
470
+ else
471
+ self[path[0]] unless path[0].nil? # force deep_merge_cache key construction if necessary
472
+ deep_merge_cache.read!(*path)
473
+ end
462
474
  end
463
475
 
464
476
  def exist?(*path)
465
- merged_attributes.exist?(*path)
477
+ if path[0].nil?
478
+ true
479
+ else
480
+ self[path[0]] unless path[0].nil? # force deep_merge_cache key construction if necessary
481
+ deep_merge_cache.exist?(*path)
482
+ end
466
483
  end
467
484
 
468
485
  def write(level, *args, &block)
@@ -30,7 +30,7 @@ class Chef
30
30
  @merged_attributes = nil
31
31
  @combined_override = nil
32
32
  @combined_default = nil
33
- @deep_merge_cache = {}
33
+ @deep_merge_cache = Chef::Node::ImmutableMash.new
34
34
  end
35
35
 
36
36
  # Invalidate a key in the deep_merge_cache. If called with nil, or no arg, this will invalidate
@@ -39,9 +39,9 @@ class Chef
39
39
  # must invalidate the entire cache and re-deep-merge the entire node object.
40
40
  def reset_cache(path = nil)
41
41
  if path.nil?
42
- deep_merge_cache.clear
42
+ deep_merge_cache.regular_clear
43
43
  else
44
- deep_merge_cache.delete(path.to_s)
44
+ deep_merge_cache.regular_delete(path.to_s)
45
45
  end
46
46
  end
47
47
 
@@ -53,7 +53,7 @@ class Chef
53
53
  deep_merge_cache[key.to_s]
54
54
  else
55
55
  # save all the work of computing node[key]
56
- deep_merge_cache[key.to_s] = merged_attributes(key)
56
+ deep_merge_cache.internal_set(key.to_s, merged_attributes(key))
57
57
  end
58
58
  ret = ret.call while ret.is_a?(::Chef::DelayedEvaluator)
59
59
  ret
@@ -73,6 +73,7 @@ class Chef
73
73
  include?
74
74
  index
75
75
  inject
76
+ intersect?
76
77
  intersection
77
78
  join
78
79
  last
@@ -248,8 +248,7 @@ class Chef
248
248
  end
249
249
 
250
250
  def api_service
251
- @api_service ||= Chef::ServerAPI.new(config[:chef_server_url],
252
- { version_class: Chef::CookbookManifestVersions })
251
+ @api_service ||= Chef::ServerAPI.new(config[:chef_server_url], version_class: Chef::CookbookManifestVersions )
253
252
  end
254
253
 
255
254
  def config
@@ -507,7 +507,7 @@ class Chef
507
507
  # @api private
508
508
  def api_service
509
509
  @api_service ||= Chef::ServerAPI.new(config[:chef_server_url],
510
- { version_class: Chef::CookbookManifestVersions })
510
+ version_class: Chef::CookbookManifestVersions)
511
511
  end
512
512
 
513
513
  # @api private
data/lib/chef/property.rb CHANGED
@@ -113,9 +113,11 @@ class Chef
113
113
  # and the transformed value returned as output. Lazy values will *not*
114
114
  # be passed to this method until after they are evaluated. Called in the
115
115
  # context of the resource (meaning you can access other properties).
116
- # @option options [Boolean] :required `true` if this property
117
- # must be present; `false` otherwise. This is checked after the resource
118
- # is fully initialized.
116
+ # @option options [Boolean, Array<Symbol>] :required `true` if this property
117
+ # must be present for *all* actions; `false` otherwise. Alternatively
118
+ # you may specify a list of actions the property is required for, when
119
+ # the property is only required for a subset of actions. This is checked
120
+ # after the resource is fully initialized.
119
121
  # @option options [String] :deprecated If set, this property is deprecated and
120
122
  # will create a deprecation warning.
121
123
  #
@@ -17,7 +17,7 @@
17
17
  #
18
18
 
19
19
  require_relative "../user"
20
- if RUBY_PLATFORM.match?(/mswin|mingw32|windows/)
20
+ if RUBY_PLATFORM.match?(/mswin|mingw|windows/)
21
21
  require_relative "../../util/windows/net_group"
22
22
  end
23
23