chef 18.4.2 → 18.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (223) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -1
  3. data/chef.gemspec +7 -7
  4. data/lib/chef/application/client.rb +12 -0
  5. data/lib/chef/client.rb +10 -16
  6. data/lib/chef/compliance/runner.rb +10 -0
  7. data/lib/chef/cookbook/chefignore.rb +4 -1
  8. data/lib/chef/cookbook/cookbook_version_loader.rb +1 -1
  9. data/lib/chef/cookbook/synchronizer.rb +7 -1
  10. data/lib/chef/cookbook_manifest.rb +2 -2
  11. data/lib/chef/file_access_control/unix.rb +9 -9
  12. data/lib/chef/file_cache.rb +17 -2
  13. data/lib/chef/file_content_management/deploy/target_io.rb +29 -0
  14. data/lib/chef/file_content_management/deploy.rb +4 -1
  15. data/lib/chef/formatters/doc.rb +1 -1
  16. data/lib/chef/mixin/file_class.rb +3 -1
  17. data/lib/chef/mixin/get_source_from_package.rb +1 -1
  18. data/lib/chef/mixin/openssl_helper.rb +1 -1
  19. data/lib/chef/node/attribute.rb +3 -11
  20. data/lib/chef/node/immutable_collections.rb +15 -8
  21. data/lib/chef/node/mixin/state_tracking.rb +6 -3
  22. data/lib/chef/node.rb +1 -1
  23. data/lib/chef/policy_builder/policyfile.rb +8 -0
  24. data/lib/chef/provider/.gitkeep +0 -0
  25. data/lib/chef/provider/cookbook_file.rb +1 -1
  26. data/lib/chef/provider/cron.rb +1 -1
  27. data/lib/chef/provider/directory.rb +15 -15
  28. data/lib/chef/provider/file.rb +42 -29
  29. data/lib/chef/provider/git.rb +8 -8
  30. data/lib/chef/provider/group/aix.rb +1 -1
  31. data/lib/chef/provider/group/dscl.rb +1 -1
  32. data/lib/chef/provider/group/gpasswd.rb +2 -2
  33. data/lib/chef/provider/group/groupadd.rb +1 -1
  34. data/lib/chef/provider/group/groupmod.rb +2 -2
  35. data/lib/chef/provider/group/pw.rb +2 -2
  36. data/lib/chef/provider/group/solaris.rb +2 -2
  37. data/lib/chef/provider/group/usermod.rb +2 -2
  38. data/lib/chef/provider/group.rb +1 -1
  39. data/lib/chef/provider/http_request.rb +2 -3
  40. data/lib/chef/provider/ifconfig/aix.rb +1 -1
  41. data/lib/chef/provider/ifconfig/debian.rb +3 -3
  42. data/lib/chef/provider/ifconfig/redhat.rb +1 -1
  43. data/lib/chef/provider/ifconfig.rb +1 -1
  44. data/lib/chef/provider/link.rb +10 -10
  45. data/lib/chef/provider/mount/aix.rb +4 -4
  46. data/lib/chef/provider/mount/linux.rb +4 -4
  47. data/lib/chef/provider/mount/mount.rb +11 -11
  48. data/lib/chef/provider/package/apt.rb +2 -11
  49. data/lib/chef/provider/package/bff.rb +3 -3
  50. data/lib/chef/provider/package/chocolatey.rb +54 -24
  51. data/lib/chef/provider/package/dpkg.rb +3 -3
  52. data/lib/chef/provider/package/freebsd/base.rb +1 -1
  53. data/lib/chef/provider/package/habitat.rb +5 -3
  54. data/lib/chef/provider/package/ips.rb +2 -2
  55. data/lib/chef/provider/package/openbsd.rb +3 -2
  56. data/lib/chef/provider/package/pacman.rb +4 -4
  57. data/lib/chef/provider/package/paludis.rb +2 -2
  58. data/lib/chef/provider/package/portage.rb +1 -1
  59. data/lib/chef/provider/package/powershell.rb +1 -0
  60. data/lib/chef/provider/package/rpm.rb +2 -2
  61. data/lib/chef/provider/package/smartos.rb +2 -2
  62. data/lib/chef/provider/package/snap.rb +2 -1
  63. data/lib/chef/provider/package/snap_tm.rb +79 -0
  64. data/lib/chef/provider/package/solaris.rb +4 -4
  65. data/lib/chef/provider/package/zypper.rb +4 -5
  66. data/lib/chef/provider/package.rb +1 -1
  67. data/lib/chef/provider/remote_directory.rb +5 -5
  68. data/lib/chef/provider/remote_file/http.rb +2 -3
  69. data/lib/chef/provider/remote_file.rb +1 -1
  70. data/lib/chef/provider/route.rb +9 -9
  71. data/lib/chef/provider/service/aix.rb +1 -1
  72. data/lib/chef/provider/service/aixinit.rb +4 -4
  73. data/lib/chef/provider/service/arch.rb +6 -6
  74. data/lib/chef/provider/service/debian.rb +5 -5
  75. data/lib/chef/provider/service/freebsd.rb +7 -7
  76. data/lib/chef/provider/service/gentoo.rb +5 -5
  77. data/lib/chef/provider/service/init.rb +2 -2
  78. data/lib/chef/provider/service/insserv.rb +2 -2
  79. data/lib/chef/provider/service/invokercd.rb +1 -1
  80. data/lib/chef/provider/service/openbsd.rb +7 -7
  81. data/lib/chef/provider/service/redhat.rb +3 -3
  82. data/lib/chef/provider/service/solaris.rb +2 -2
  83. data/lib/chef/provider/service/systemd.rb +2 -2
  84. data/lib/chef/provider/service/upstart.rb +2 -2
  85. data/lib/chef/provider/service/windows.rb +0 -1
  86. data/lib/chef/provider/subversion.rb +8 -8
  87. data/lib/chef/provider/systemd_unit.rb +3 -3
  88. data/lib/chef/provider/template.rb +1 -1
  89. data/lib/chef/provider/user/aix.rb +3 -3
  90. data/lib/chef/provider/user/linux.rb +7 -2
  91. data/lib/chef/provider/user/pw.rb +3 -3
  92. data/lib/chef/provider/user/solaris.rb +7 -7
  93. data/lib/chef/provider/user.rb +7 -8
  94. data/lib/chef/provider/yum_repository.rb +1 -3
  95. data/lib/chef/provider/zypper_repository.rb +1 -1
  96. data/lib/chef/providers.rb +1 -0
  97. data/lib/chef/resource/.gitkeep +0 -0
  98. data/lib/chef/resource/alternatives.rb +2 -2
  99. data/lib/chef/resource/apt_preference.rb +1 -1
  100. data/lib/chef/resource/apt_repository.rb +7 -9
  101. data/lib/chef/resource/apt_update.rb +3 -3
  102. data/lib/chef/resource/bff_package.rb +1 -1
  103. data/lib/chef/resource/chef_client_config.rb +3 -2
  104. data/lib/chef/resource/chef_client_systemd_timer.rb +5 -0
  105. data/lib/chef/resource/chef_gem.rb +1 -1
  106. data/lib/chef/resource/chef_sleep.rb +1 -1
  107. data/lib/chef/resource/cookbook_file.rb +1 -1
  108. data/lib/chef/resource/cron/cron.rb +1 -1
  109. data/lib/chef/resource/cron/cron_d.rb +1 -1
  110. data/lib/chef/resource/cron_access.rb +1 -1
  111. data/lib/chef/resource/directory.rb +1 -1
  112. data/lib/chef/resource/dpkg_package.rb +1 -1
  113. data/lib/chef/resource/execute.rb +8 -6
  114. data/lib/chef/resource/file/verification/json.rb +1 -1
  115. data/lib/chef/resource/file/verification/systemd_unit.rb +1 -1
  116. data/lib/chef/resource/file/verification/yaml.rb +1 -1
  117. data/lib/chef/resource/file.rb +1 -1
  118. data/lib/chef/resource/freebsd_package.rb +2 -2
  119. data/lib/chef/resource/group.rb +1 -1
  120. data/lib/chef/resource/habitat/habitat_package.rb +1 -1
  121. data/lib/chef/resource/habitat/habitat_sup.rb +9 -9
  122. data/lib/chef/resource/habitat/habitat_sup_systemd.rb +2 -2
  123. data/lib/chef/resource/habitat_install.rb +5 -4
  124. data/lib/chef/resource/hostname.rb +11 -10
  125. data/lib/chef/resource/http_request.rb +1 -1
  126. data/lib/chef/resource/ifconfig.rb +1 -1
  127. data/lib/chef/resource/inspec_input.rb +3 -1
  128. data/lib/chef/resource/inspec_waiver.rb +1 -1
  129. data/lib/chef/resource/inspec_waiver_file_entry.rb +1 -1
  130. data/lib/chef/resource/ips_package.rb +2 -2
  131. data/lib/chef/resource/kernel_module.rb +2 -2
  132. data/lib/chef/resource/link.rb +1 -1
  133. data/lib/chef/resource/locale.rb +2 -2
  134. data/lib/chef/resource/mount.rb +1 -1
  135. data/lib/chef/resource/notify_group.rb +1 -1
  136. data/lib/chef/resource/ohai.rb +1 -1
  137. data/lib/chef/resource/ohai_hint.rb +1 -1
  138. data/lib/chef/resource/openbsd_package.rb +2 -2
  139. data/lib/chef/resource/package.rb +1 -1
  140. data/lib/chef/resource/pacman_package.rb +1 -1
  141. data/lib/chef/resource/paludis_package.rb +1 -1
  142. data/lib/chef/resource/portage_package.rb +1 -1
  143. data/lib/chef/resource/powershell_package.rb +4 -0
  144. data/lib/chef/resource/reboot.rb +1 -1
  145. data/lib/chef/resource/remote_directory.rb +1 -1
  146. data/lib/chef/resource/remote_file.rb +1 -1
  147. data/lib/chef/resource/rhsm_errata.rb +1 -1
  148. data/lib/chef/resource/rhsm_errata_level.rb +1 -1
  149. data/lib/chef/resource/rhsm_register.rb +1 -1
  150. data/lib/chef/resource/rhsm_repo.rb +3 -4
  151. data/lib/chef/resource/rhsm_subscription.rb +8 -9
  152. data/lib/chef/resource/route.rb +1 -1
  153. data/lib/chef/resource/rpm_package.rb +1 -1
  154. data/lib/chef/resource/scm/git.rb +1 -1
  155. data/lib/chef/resource/scm/subversion.rb +1 -1
  156. data/lib/chef/resource/selinux/common_helpers.rb +1 -1
  157. data/lib/chef/resource/selinux_boolean.rb +1 -1
  158. data/lib/chef/resource/selinux_fcontext.rb +3 -3
  159. data/lib/chef/resource/selinux_install.rb +1 -1
  160. data/lib/chef/resource/selinux_login.rb +1 -1
  161. data/lib/chef/resource/selinux_module.rb +5 -5
  162. data/lib/chef/resource/selinux_permissive.rb +2 -2
  163. data/lib/chef/resource/selinux_port.rb +2 -2
  164. data/lib/chef/resource/selinux_state.rb +2 -2
  165. data/lib/chef/resource/selinux_user.rb +1 -1
  166. data/lib/chef/resource/smartos_package.rb +2 -2
  167. data/lib/chef/resource/snap_package.rb +24 -1
  168. data/lib/chef/resource/solaris_package.rb +1 -1
  169. data/lib/chef/resource/ssh_known_hosts_entry.rb +1 -1
  170. data/lib/chef/resource/sudo.rb +5 -5
  171. data/lib/chef/resource/support/client.erb +1 -1
  172. data/lib/chef/resource/swap_file.rb +6 -6
  173. data/lib/chef/resource/sysctl.rb +6 -5
  174. data/lib/chef/resource/systemd_unit.rb +1 -1
  175. data/lib/chef/resource/template.rb +1 -1
  176. data/lib/chef/resource/timezone.rb +5 -5
  177. data/lib/chef/resource/user/aix_user.rb +2 -2
  178. data/lib/chef/resource/user/linux_user.rb +2 -2
  179. data/lib/chef/resource/user/pw_user.rb +2 -2
  180. data/lib/chef/resource/user/solaris_user.rb +2 -2
  181. data/lib/chef/resource/user_ulimit.rb +1 -1
  182. data/lib/chef/resource/yum_repository.rb +1 -1
  183. data/lib/chef/resource/zypper_package.rb +2 -2
  184. data/lib/chef/resource/zypper_repository.rb +2 -2
  185. data/lib/chef/run_lock.rb +3 -0
  186. data/lib/chef/scan_access_control.rb +6 -6
  187. data/lib/chef/target_io/dir.rb +12 -0
  188. data/lib/chef/target_io/etc.rb +16 -0
  189. data/lib/chef/target_io/file.rb +12 -0
  190. data/lib/chef/target_io/fileutils.rb +12 -0
  191. data/lib/chef/target_io/http.rb +22 -0
  192. data/lib/chef/target_io/io.rb +12 -0
  193. data/lib/chef/target_io/shadow.rb +44 -0
  194. data/lib/chef/target_io/train/dir.rb +69 -0
  195. data/lib/chef/target_io/train/etc.rb +112 -0
  196. data/lib/chef/target_io/train/file.rb +219 -0
  197. data/lib/chef/target_io/train/fileutils.rb +220 -0
  198. data/lib/chef/target_io/train/http.rb +117 -0
  199. data/lib/chef/target_io/train/io.rb +13 -0
  200. data/lib/chef/target_io/train/shadow.rb +52 -0
  201. data/lib/chef/target_io/train_compat.rb +7 -0
  202. data/lib/chef/target_io.rb +9 -0
  203. data/lib/chef/util/backup.rb +1 -1
  204. data/lib/chef/util/diff.rb +14 -1
  205. data/lib/chef/util/file_edit.rb +4 -4
  206. data/lib/chef/version.rb +1 -1
  207. data/lib/chef.rb +2 -0
  208. data/spec/functional/resource/remote_file_spec.rb +1 -1
  209. data/spec/integration/client/fips_spec.rb +11 -2
  210. data/spec/integration/client/open_ssl_spec.rb +20 -0
  211. data/spec/spec_helper.rb +3 -1
  212. data/spec/support/platform_helpers.rb +20 -7
  213. data/spec/unit/client_spec.rb +0 -16
  214. data/spec/unit/file_cache_spec.rb +64 -0
  215. data/spec/unit/mixin/openssl_helper_spec.rb +6 -1
  216. data/spec/unit/provider/apt_repository_spec.rb +1 -1
  217. data/spec/unit/provider/package/chocolatey_spec.rb +17 -12
  218. data/spec/unit/provider/package/windows_spec.rb +5 -5
  219. data/spec/unit/provider/package/zypper_spec.rb +0 -10
  220. data/spec/unit/provider/route_spec.rb +6 -4
  221. data/spec/unit/resource/rhsm_repo_spec.rb +1 -0
  222. data/spec/unit/resource/rhsm_subscription_spec.rb +2 -0
  223. metadata +31 -10
@@ -0,0 +1,117 @@
1
+ # require_relative "../mixin/which"
2
+
3
+ module TargetIO
4
+ module TrainCompat
5
+ class HTTP
6
+ attr_reader :last_response
7
+
8
+ def initialize(url, options = {})
9
+ @url = url.is_a?(URI) ? url.to_s : url
10
+ @options = options
11
+ @last_response = ""
12
+ end
13
+
14
+ # Send an HTTP HEAD request to the path
15
+ #
16
+ # === Parameters
17
+ # path:: path part of the request URL
18
+ def head(path, headers = {})
19
+ request(:HEAD, path, headers)
20
+ end
21
+
22
+ # Send an HTTP GET request to the path
23
+ #
24
+ # === Parameters
25
+ # path:: The path to GET
26
+ def get(path, headers = {})
27
+ request(:GET, path, headers)
28
+ end
29
+
30
+ # Send an HTTP PUT request to the path
31
+ #
32
+ # === Parameters
33
+ # path:: path part of the request URL
34
+ def put(path, json, headers = {})
35
+ request(:PUT, path, headers, json)
36
+ end
37
+
38
+ # Send an HTTP POST request to the path
39
+ #
40
+ # === Parameters
41
+ # path:: path part of the request URL
42
+ def post(path, json, headers = {})
43
+ request(:POST, path, headers, json)
44
+ end
45
+
46
+ # Send an HTTP DELETE request to the path
47
+ #
48
+ # === Parameters
49
+ # path:: path part of the request URL
50
+ def delete(path, headers = {})
51
+ request(:DELETE, path, headers)
52
+ end
53
+
54
+ # Used inside Chef::Provider::RemoteFile::HTTPS
55
+ def streaming_request(path, headers = {}, tempfile = nil)
56
+ content = get(path, headers)
57
+ @last_response = content
58
+
59
+ tempfile.write(content)
60
+ tempfile.close
61
+
62
+ tempfile
63
+ end
64
+
65
+ def request(method, path, headers = {}, data = false)
66
+ cmd = nil
67
+ path = path.is_a?(URI) ? path.to_s : path
68
+ headers.merge!(@options[:headers] || {})
69
+
70
+ SUPPORTED_COMMANDS.each do |command_name|
71
+ executable = which(command_name).chop
72
+ next if !executable || executable.empty?
73
+
74
+ # There are different ways to call (constructor, argument, combination of both)
75
+ full_url = if path.start_with?("http")
76
+ path
77
+ elsif path.empty? || @url.end_with?(path)
78
+ @url
79
+ else
80
+ File.join(@url, path)
81
+ end
82
+
83
+ cmd = send(command_name.to_sym, executable, method.to_s.upcase, full_url, headers, data)
84
+ break
85
+ end
86
+
87
+ raise "Target needs one of #{SUPPORTED_COMMANDS.join("/")} for HTTP requests to work" unless cmd
88
+
89
+ connection = Chef.run_context&.transport_connection
90
+ connection.run_command(cmd).stdout
91
+ end
92
+
93
+ SUPPORTED_COMMANDS = %w{curl wget}.freeze
94
+
95
+ # Sending data is not yet supported
96
+ def curl(cmd, method, url, headers, _data)
97
+ cmd += headers.map { |name, value| " --header '#{name}: #{value}'" }.join
98
+ cmd += " --request #{method} "
99
+ cmd += url
100
+ end
101
+
102
+ # Sending data is not yet supported
103
+ def wget(cmd, method, url, headers, _data)
104
+ cmd += headers.map { |name, value| " --header '#{name}: #{value}'" }.join
105
+ cmd += " --method #{method}"
106
+ cmd += " --output-document=- "
107
+ cmd += url
108
+ end
109
+
110
+ # extend Chef::Mixin::Which
111
+ def which(cmd)
112
+ connection = Chef.run_context&.transport_connection
113
+ connection.run_command("which #{cmd}").stdout
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,13 @@
1
+ require_relative "file"
2
+
3
+ module TargetIO
4
+ module TrainCompat
5
+ class IO
6
+ class << self
7
+ def read(path)
8
+ TargetIO::File.read(path)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,52 @@
1
+ module TargetIO
2
+ module TrainCompat
3
+ module Shadow
4
+ # @see https://www.rubydoc.info/gems/ruby-shadow/2.5.0
5
+ class Passwd
6
+ class << self
7
+ def getspnam(name)
8
+ content = ::TargetIO::File.read("/etc/shadow")
9
+ entries = __parse_shadow(content)
10
+ data = entries.detect { |entry| entry["name"] == name }
11
+ return ::TargetIO::Shadow::Entry.new unless data
12
+
13
+ ::TargetIO::Shadow::Entry.new(
14
+ data["sp_namp"],
15
+ data["sp_pwdp"],
16
+ data["sp_lstchg"],
17
+ data["sp_min"],
18
+ data["sp_max"],
19
+ data["sp_warn"],
20
+ data["sp_inact"],
21
+ data["sp_expire"],
22
+ data["sp_loginclass"]
23
+ )
24
+ end
25
+
26
+ def __parse_shadow(content)
27
+ content.to_s.split("\n").map do |line|
28
+ next if line[0] == "#"
29
+
30
+ __parse_shadow_line(line)
31
+ end.compact
32
+ end
33
+
34
+ def __parse_shadow_line(line)
35
+ x = line.split(":")
36
+ {
37
+ # rubocop:disable Layout/AlignHash
38
+ "sp_namp" => x.at(0),
39
+ "sp_pwdp" => x.at(1),
40
+ "sp_lstchg" => x.at(2),
41
+ "sp_min" => x.at(3),
42
+ "sp_max" => x.at(4),
43
+ "sp_warn" => x.at(5),
44
+ "sp_inact" => x.at(6),
45
+ "sp_expire" => x.at(7),
46
+ }
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,7 @@
1
+ require_relative "train/dir"
2
+ require_relative "train/etc"
3
+ require_relative "train/file"
4
+ require_relative "train/fileutils"
5
+ require_relative "train/http"
6
+ require_relative "train/io"
7
+ require_relative "train/shadow"
@@ -0,0 +1,9 @@
1
+ require_relative "target_io/dir"
2
+ require_relative "target_io/etc"
3
+ require_relative "target_io/file"
4
+ require_relative "target_io/fileutils"
5
+ require_relative "target_io/http"
6
+ require_relative "target_io/io"
7
+ require_relative "target_io/shadow"
8
+
9
+ require_relative "target_io/train_compat"
@@ -30,7 +30,7 @@ class Chef
30
30
  end
31
31
 
32
32
  def backup!
33
- if @new_resource.backup != false && @new_resource.backup > 0 && ::File.exist?(path)
33
+ if @new_resource.backup != false && @new_resource.backup > 0 && ::TargetIO::File.exist?(path)
34
34
  do_backup
35
35
  # Clean up after the number of backups
36
36
  slice_number = @new_resource.backup
@@ -60,7 +60,7 @@ class Chef
60
60
 
61
61
  def use_tempfile_if_missing(file)
62
62
  tempfile = nil
63
- unless File.exist?(file)
63
+ unless TargetIO::File.exist?(file)
64
64
  Chef::Log.trace("File #{file} does not exist to diff against, using empty tempfile")
65
65
  tempfile = Tempfile.new("chef-diff")
66
66
  file = tempfile.path
@@ -131,6 +131,19 @@ class Chef
131
131
  diff_filesize_threshold = Chef::Config[:diff_filesize_threshold]
132
132
  diff_output_threshold = Chef::Config[:diff_output_threshold]
133
133
 
134
+ # Download files for diffs in Target Mode, then work locally
135
+ if ChefConfig::Config.target_mode?
136
+ connection = Chef.run_context&.transport_connection
137
+
138
+ old_copy = Tempfile.new(old_file)
139
+ connection.download(old_file, old_copy.path) if connection.file(old_file).exist?
140
+ old_file = old_copy.path
141
+
142
+ new_copy = Tempfile.new(new_file)
143
+ connection.download(new_file, new_copy.path) if connection.file(new_file).exist?
144
+ new_file = new_copy.path
145
+ end
146
+
134
147
  if ::File.size(old_file) > diff_filesize_threshold || ::File.size(new_file) > diff_filesize_threshold
135
148
  return "(file sizes exceed #{diff_filesize_threshold} bytes, diff output suppressed)"
136
149
  end
@@ -29,9 +29,9 @@ class Chef
29
29
  public
30
30
 
31
31
  def initialize(filepath)
32
- raise ArgumentError, "File '#{filepath}' does not exist" unless File.exist?(filepath)
32
+ raise ArgumentError, "File '#{filepath}' does not exist" unless TargetIO::File.exist?(filepath)
33
33
 
34
- @editor = Editor.new(File.open(filepath, &:readlines))
34
+ @editor = Editor.new(TargetIO::File.open(filepath, &:readlines))
35
35
  @original_pathname = filepath
36
36
  @file_edited = false
37
37
  end
@@ -85,8 +85,8 @@ class Chef
85
85
  def write_file
86
86
  if @changes
87
87
  backup_pathname = original_pathname + ".old"
88
- FileUtils.cp(original_pathname, backup_pathname, preserve: true)
89
- File.open(original_pathname, "w") do |newfile|
88
+ TargetIO::FileUtils.cp(original_pathname, backup_pathname, preserve: true)
89
+ TargetIO::File.open(original_pathname, "w") do |newfile|
90
90
  editor.lines.each do |line|
91
91
  newfile.puts(line)
92
92
  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("18.4.2")
26
+ VERSION = Chef::VersionString.new("18.5.0")
27
27
  end
28
28
 
29
29
  #
data/lib/chef.rb CHANGED
@@ -32,3 +32,5 @@ require_relative "chef/handler"
32
32
  require_relative "chef/handler/json_file"
33
33
  require_relative "chef/event_dispatch/dsl"
34
34
  require_relative "chef/chef_class"
35
+
36
+ require_relative "chef/target_io"
@@ -245,7 +245,7 @@ describe Chef::Resource::RemoteFile do
245
245
  end
246
246
  end
247
247
 
248
- context "when the the file is only accessible as a specific alternate identity" do
248
+ context "when the file is only accessible as a specific alternate identity" do
249
249
  let(:windows_nonadmin_user) { "chefremfile2" }
250
250
  let(:windows_nonadmin_user_password) { "j82ajfxK3;2Xe2" }
251
251
  include_context "a non-admin Windows user"
@@ -9,12 +9,21 @@ describe "chef-client fips" do
9
9
  after { OpenSSL.fips_mode = false }
10
10
 
11
11
  # For non-FIPS OSes/builds of Ruby, enabling FIPS should error
12
- example "Error enabling fips_mode if FIPS not linked", fips_mode: false do
12
+ example "Error enabling fips_mode if FIPS not linked", :fips_mode_negative_test do
13
13
  expect { enable_fips }.to raise_error(OpenSSL::OpenSSLError)
14
14
  end
15
15
 
16
+ example "Do not error on MD5 if not fips_mode", :fips_mode_negative_test do
17
+ expect { OpenSSL::Digest.new("MD5", "test string for digesting") }.not_to raise_error
18
+ end
19
+
16
20
  # For FIPS OSes/builds of Ruby, enabling FIPS should not error
17
- example "Do not error enabling fips_mode if FIPS linked", fips_mode: true do
21
+ example "Do not error enabling fips_mode if FIPS linked", :fips_mode_test do
18
22
  expect { enable_fips }.not_to raise_error
19
23
  end
24
+
25
+ example "Error on MD5 if fips_mode", :fips_mode_test do
26
+ enable_fips
27
+ expect { OpenSSL::Digest.new("MD5", "test string for digesting") }.to raise_error(OpenSSL::Digest::DigestError)
28
+ end
20
29
  end
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+
3
+ describe "openssl checks" do
4
+ let(:openssl_version_default) do
5
+ if windows?
6
+ "1.0.2zi"
7
+ elsif macos?
8
+ "1.1.1m"
9
+ else
10
+ "3.0.9"
11
+ end
12
+ end
13
+
14
+ %w{version library_version}.each do |method|
15
+ # macOS just picks up its own for some reason, maybe it circumvents a build step
16
+ example "check #{method}", not_supported_on_macos: true do
17
+ expect(OpenSSL.const_get("OPENSSL_#{method.upcase}")).to match(openssl_version_default), "OpenSSL doesn't match omnibus_overrides.rb"
18
+ end
19
+ end
20
+ end
data/spec/spec_helper.rb CHANGED
@@ -138,7 +138,8 @@ RSpec.configure do |config|
138
138
 
139
139
  config.filter_run_excluding skip_buildkite: true if ENV["BUILDKITE"]
140
140
 
141
- config.filter_run_excluding fips_mode: !fips_mode_build?
141
+ config.filter_run_excluding fips_mode_test: true unless fips_mode_build?
142
+ config.filter_run_excluding fips_mode_negative_test: true # disable all fips_mode negative tests
142
143
  # Skip fips on windows
143
144
  # config.filter_run_excluding :fips_mode if windows?
144
145
 
@@ -180,6 +181,7 @@ RSpec.configure do |config|
180
181
  config.filter_run_excluding aes_256_gcm_only: true unless aes_256_gcm?
181
182
  config.filter_run_excluding broken: true
182
183
  config.filter_run_excluding not_wpar: true unless wpar?
184
+ config.filter_run_excluding not_supported_on_s390x: true unless s390x?
183
185
  config.filter_run_excluding not_supported_under_fips: true if fips?
184
186
  config.filter_run_excluding rhel: true unless rhel?
185
187
  config.filter_run_excluding rhel6: true unless rhel6?
@@ -67,10 +67,10 @@ end
67
67
 
68
68
  def win32_os_version
69
69
  @win32_os_version ||= begin
70
- wmi = WmiLite::Wmi.new
71
- host = wmi.first_of("Win32_OperatingSystem")
72
- host["version"]
73
- end
70
+ wmi = WmiLite::Wmi.new
71
+ host = wmi.first_of("Win32_OperatingSystem")
72
+ host["version"]
73
+ end
74
74
  end
75
75
 
76
76
  def windows_powershell_dsc?
@@ -80,7 +80,7 @@ def windows_powershell_dsc?
80
80
  begin
81
81
  wmi = WmiLite::Wmi.new("root/microsoft/windows/desiredstateconfiguration")
82
82
  lcm = wmi.query("SELECT * FROM meta_class WHERE __this ISA 'MSFT_DSCLocalConfigurationManager'")
83
- supports_dsc = !! lcm
83
+ supports_dsc = !!lcm
84
84
  rescue WmiLite::WmiException
85
85
  end
86
86
  supports_dsc
@@ -95,7 +95,7 @@ end
95
95
 
96
96
  # detects if the hardware is 64-bit (evaluates to true in "WOW64" mode in a 32-bit app on a 64-bit system)
97
97
  def windows64?
98
- windows? && ( ENV["PROCESSOR_ARCHITECTURE"] == "AMD64" || ENV["PROCESSOR_ARCHITEW6432"] == "AMD64" )
98
+ windows? && (ENV["PROCESSOR_ARCHITECTURE"] == "AMD64" || ENV["PROCESSOR_ARCHITEW6432"] == "AMD64")
99
99
  end
100
100
 
101
101
  # detects if the hardware is 32-bit
@@ -175,6 +175,10 @@ def wpar?
175
175
  !((ohai[:virtualization] || {})[:wpar_no].nil?)
176
176
  end
177
177
 
178
+ def s390x?
179
+ RUBY_PLATFORM.include?("s390x")
180
+ end
181
+
178
182
  def supports_cloexec?
179
183
  Fcntl.const_defined?(:F_SETFD) && Fcntl.const_defined?(:FD_CLOEXEC)
180
184
  end
@@ -224,7 +228,15 @@ def aes_256_gcm?
224
228
  end
225
229
 
226
230
  def fips_mode_build?
227
- OpenSSL::OPENSSL_FIPS
231
+ if ENV.include?("BUILDKITE_LABEL") # try keying directly off Buildkite environments
232
+ # regex version of chef/chef-foundation:.expeditor/release.omnibus.yml:fips-platforms
233
+ [/el-.*-x86_64/, /el-.*-ppc64/, /el-.*aarch/, /ubuntu-/, /windows-/, /amazon-2/].any? do |os_arch|
234
+ ENV["BUILDKITE_LABEL"].match?(os_arch)
235
+ end
236
+ else
237
+ # if you're testing your local build
238
+ OpenSSL::OPENSSL_FIPS
239
+ end
228
240
  end
229
241
 
230
242
  def fips?
@@ -233,6 +245,7 @@ end
233
245
 
234
246
  class HttpHelper
235
247
  extend Ohai::Mixin::HttpHelper
248
+
236
249
  def self.logger
237
250
  Chef::Log
238
251
  end
@@ -384,22 +384,6 @@ describe Chef::Client do
384
384
  end
385
385
  end
386
386
 
387
- describe "eol release warning" do
388
- it "warns when running an EOL release" do
389
- stub_const("Chef::VERSION", 15)
390
- allow(Time).to receive(:now).and_return(Time.new(2021, 5, 1, 5))
391
- expect(logger).to receive(:warn).with(/This release of.*became end of life \(EOL\) on May 1st 2021/)
392
- client.warn_if_eol
393
- end
394
-
395
- it "does not warn when running an non-EOL release" do
396
- stub_const("Chef::VERSION", 15)
397
- allow(Time).to receive(:now).and_return(Time.new(2021, 4, 31))
398
- expect(logger).to_not receive(:warn).with(/became end of life/)
399
- client.warn_if_eol
400
- end
401
- end
402
-
403
387
  describe "authentication protocol selection" do
404
388
  context "when FIPS is disabled" do
405
389
  before do
@@ -94,7 +94,71 @@ describe Chef::FileCache do
94
94
  it "searches for cached files by globbing" do
95
95
  expect(Chef::FileCache.find("snappy/**/*")).to eq(%w{snappy/patter})
96
96
  end
97
+ end
98
+
99
+ describe "#find handles regex-unsafe unix paths" do
100
+ before(:each) do
101
+ # Dir.mktmpdir doesn't allow regex unsafe characters (the nerve!), so we'll have to fake file lookups
102
+ @file_cache_path = "/tmp/[foo* ^bar]"
103
+ escaped_file_cache_path = '/tmp/\[foo\* ^bar\]'
104
+ Chef::Config[:file_cache_path] = @file_cache_path
105
+ allow(Chef::Util::PathHelper).to receive(:escape_glob_dir).and_return(escaped_file_cache_path)
106
+ allow(Dir).to receive(:[]).with(File.join(escaped_file_cache_path, "snappy/**/*")).and_return([
107
+ File.join(@file_cache_path, "snappy"),
108
+ File.join(@file_cache_path, "snappy", "patter"),
109
+ ])
110
+ allow(Dir).to receive(:[]).with(escaped_file_cache_path).and_return([
111
+ @file_cache_path,
112
+ ])
113
+ [
114
+ File.join(@file_cache_path, "snappy", "patter"),
115
+ File.join(@file_cache_path, "whiz", "bang"),
116
+ ].each do |f|
117
+ allow(File).to receive(:file?).with(f).and_return(true)
118
+ end
119
+ [
120
+ File.join(@file_cache_path, "snappy"),
121
+ File.join(@file_cache_path, "whiz"),
122
+ ].each do |f|
123
+ allow(File).to receive(:file?).with(f).and_return(false)
124
+ end
125
+ end
126
+
127
+ it "searches for cached files by globbing" do
128
+ expect(Chef::FileCache.find("snappy/**/*")).to eq(%w{snappy/patter})
129
+ end
130
+ end
97
131
 
132
+ describe "#find handles Windows paths" do
133
+ before(:each) do
134
+ allow(ChefUtils).to receive(:windows?).and_return(true)
135
+ @file_cache_path = 'C:\tmp\fakecache'
136
+ escaped_file_cache_path = "C:\\tmp\\fakecache"
137
+ Chef::Config[:file_cache_path] = @file_cache_path
138
+ allow(Chef::Util::PathHelper).to receive(:escape_glob_dir).and_return(escaped_file_cache_path)
139
+ allow(Dir).to receive(:[]).with(File.join(escaped_file_cache_path, "snappy/**/*")).and_return([
140
+ File.join(@file_cache_path, "snappy"),
141
+ File.join(@file_cache_path, "snappy", "patter"),
142
+ ])
143
+ allow(Dir).to receive(:[]).with(escaped_file_cache_path).and_return([
144
+ @file_cache_path,
145
+ ])
146
+ [
147
+ File.join(@file_cache_path, "snappy", "patter"),
148
+ File.join(@file_cache_path, "whiz", "bang"),
149
+ ].each do |f|
150
+ allow(File).to receive(:file?).with(f).and_return(true)
151
+ end
152
+ [
153
+ File.join(@file_cache_path, "snappy"),
154
+ File.join(@file_cache_path, "whiz"),
155
+ ].each do |f|
156
+ allow(File).to receive(:file?).with(f).and_return(false)
157
+ end
158
+ end
159
+ it "searches for cached files by globbing" do
160
+ expect(Chef::FileCache.find("snappy/**/*")).to eq(%w{snappy/patter})
161
+ end
98
162
  end
99
163
 
100
164
  describe "when checking for the existence of a file" do
@@ -92,7 +92,12 @@ describe Chef::Mixin::OpenSSLHelper do
92
92
 
93
93
  context "When the dhparam.pem file does exist, and does contain a vaild dhparam key" do
94
94
  it "returns true" do
95
- @dhparam_file.puts(::OpenSSL::PKey::DH.new(256).to_pem) # this is 256 to speed up specs
95
+ # bumped this from 256 to 1024 because OpenSSL 3.x will enforce
96
+ # size
97
+ # OpenSSL::PKey::PKeyError:
98
+ # EVP_PKEY_paramgen: modulus too small
99
+ # need to double check that the mixin itself doesn't allow smaller
100
+ @dhparam_file.puts(::OpenSSL::PKey::DH.new(1024).to_pem)
96
101
  @dhparam_file.close
97
102
  expect(instance.dhparam_pem_valid?(@dhparam_file.path)).to be_truthy
98
103
  end
@@ -230,7 +230,7 @@ C5986B4F1257FFA86632CBA746181433FBB75451
230
230
  it "gets a key" do
231
231
  simples = double("HTTP")
232
232
  allow(simples).to receive(:get).and_return("\"#{key}\"")
233
- expect(Chef::HTTP::Simple).to receive(:new).with(url).and_return(simples)
233
+ expect(Chef::HTTP::Simple).to receive(:new).with(url, {}).and_return(simples)
234
234
  expect(provider).to receive(:install_key_from_keyserver).with(key, "keyserver.ubuntu.com")
235
235
  provider.install_ppa_key("chef", "main")
236
236
  end
@@ -36,9 +36,9 @@ describe Chef::Provider::Package::Chocolatey, :windows_only do
36
36
  # installed packages (ConEmu is upgradable)
37
37
  let(:local_list_stdout) do
38
38
  <<~EOF
39
- Chocolatey v0.9.9.11
40
- chocolatey|0.9.9.11
41
- ConEmu|15.10.25.0
39
+ Chocolatey v0.9.9.10
40
+ chocolatey|0.9.9.12
41
+ ConEmu|15.10.25.2
42
42
  EOF
43
43
  end
44
44
 
@@ -47,10 +47,10 @@ describe Chef::Provider::Package::Chocolatey, :windows_only do
47
47
  allow(provider).to receive(:choco_exe).and_return(choco_exe)
48
48
  local_list_obj = double(stdout: local_list_stdout)
49
49
  allow(provider).to receive(:shell_out_compacted!).with(choco_exe, "list", "-l", "-r", { returns: [0, 2], timeout: timeout }).and_return(local_list_obj)
50
- allow(provider).to receive(:powershell_exec!).with("#{choco_exe} --version").and_return(double(result: "2.1.0"))
50
+ allow(provider).to receive(:powershell_exec!).with("Get-ItemProperty #{choco_exe} | select-object -expandproperty versioninfo | select-object -expandproperty productversion").and_return(double(result: "2.1.0"))
51
51
  # Mock the local file system choco queries
52
52
  allow(provider).to receive(:get_local_pkg_dirs).and_return(%w{chocolatey ConEmu})
53
- allow(provider).to receive(:fetch_package_versions_local).and_return({ "chocolatey" => "0.9.9.11", "conemu" => "15.10.25.0" })
53
+ allow(provider).to receive(:fetch_package_versions).and_return({ "chocolatey" => "0.9.9.11", "conemu" => "15.10.25.0" })
54
54
  end
55
55
 
56
56
  after(:each) do
@@ -70,10 +70,13 @@ describe Chef::Provider::Package::Chocolatey, :windows_only do
70
70
  munin-node|1.6.1.20130823
71
71
  EOF
72
72
  remote_list_obj = double(stdout: remote_list_stdout)
73
- if args
74
- allow(provider).to receive(:shell_out_compacted!).with(choco_exe, provider.query_command, "-r", *(package_names.sort + args), { returns: [0, 2], timeout: timeout }).and_return(remote_list_obj)
75
- else
76
- allow(provider).to receive(:shell_out_compacted!).with(choco_exe, provider.query_command, "-r", *(package_names.sort), { returns: [0, 2], timeout: timeout }).and_return(remote_list_obj)
73
+
74
+ package_names.each do |pkg|
75
+ if args
76
+ allow(provider).to receive(:shell_out_compacted!).with(choco_exe, provider.query_command, "-r", *([pkg] + args), { returns: [0, 2], timeout: timeout }).and_return(remote_list_obj)
77
+ else
78
+ allow(provider).to receive(:shell_out_compacted!).with(choco_exe, provider.query_command, "-r", pkg, { returns: [0, 2], timeout: timeout }).and_return(remote_list_obj)
79
+ end
77
80
  end
78
81
  end
79
82
 
@@ -89,12 +92,12 @@ describe Chef::Provider::Package::Chocolatey, :windows_only do
89
92
 
90
93
  describe "choco searches change with the version" do
91
94
  it "Choco V1 uses List" do
92
- allow(provider).to receive(:powershell_exec!).with("#{choco_exe} --version").and_return(double(result: "1.4.0"))
95
+ allow(provider).to receive(:powershell_exec!).with("Get-ItemProperty #{choco_exe} | select-object -expandproperty versioninfo | select-object -expandproperty productversion").and_return(double(result: "1.4.0"))
93
96
  expect(provider.query_command).to eql("list")
94
97
  end
95
98
 
96
99
  it "Choco V2 uses Search" do
97
- allow(provider).to receive(:powershell_exec!).with("#{choco_exe} --version").and_return(double(result: "2.1.0"))
100
+ allow(provider).to receive(:powershell_exec!).with("Get-ItemProperty #{choco_exe} | select-object -expandproperty versioninfo | select-object -expandproperty productversion").and_return(double(result: "2.1.0"))
98
101
  expect(provider.query_command).to eql("search")
99
102
  end
100
103
  end
@@ -168,6 +171,7 @@ describe Chef::Provider::Package::Chocolatey, :windows_only do
168
171
 
169
172
  it "should load and downcase names in the installed_packages hash (with disk provider)" do
170
173
  new_resource.use_choco_list(false)
174
+ provider.invalidate_cache
171
175
  provider.load_current_resource
172
176
  expect(provider.send(:installed_packages)).to eql(
173
177
  { "chocolatey" => "0.9.9.11", "conemu" => "15.10.25.0" }
@@ -176,9 +180,10 @@ describe Chef::Provider::Package::Chocolatey, :windows_only do
176
180
 
177
181
  it "should load and downcase names in the installed_packages hash (with choco list provider)" do
178
182
  new_resource.use_choco_list(true)
183
+ provider.invalidate_cache
179
184
  provider.load_current_resource
180
185
  expect(provider.send(:installed_packages)).to eql(
181
- { "chocolatey" => "0.9.9.11", "conemu" => "15.10.25.0" }
186
+ { "chocolatey" => "0.9.9.12", "conemu" => "15.10.25.2" }
182
187
  )
183
188
  end
184
189
 
@@ -106,27 +106,27 @@ describe Chef::Provider::Package::Windows, :windows_only do
106
106
  provider.package_provider
107
107
  end
108
108
 
109
- it "sets the package provider to MSI if the the installer type is :msi" do
109
+ it "sets the package provider to MSI if the installer type is :msi" do
110
110
  allow(provider).to receive(:installer_type).and_return(:msi)
111
111
  expect(provider.package_provider).to be_a(Chef::Provider::Package::Windows::MSI)
112
112
  end
113
113
 
114
- it "sets the package provider to Exe if the the installer type is :inno" do
114
+ it "sets the package provider to Exe if the installer type is :inno" do
115
115
  allow(provider).to receive(:installer_type).and_return(:inno)
116
116
  expect(provider.package_provider).to be_a(Chef::Provider::Package::Windows::Exe)
117
117
  end
118
118
 
119
- it "sets the package provider to Exe if the the installer type is :nsis" do
119
+ it "sets the package provider to Exe if the installer type is :nsis" do
120
120
  allow(provider).to receive(:installer_type).and_return(:nsis)
121
121
  expect(provider.package_provider).to be_a(Chef::Provider::Package::Windows::Exe)
122
122
  end
123
123
 
124
- it "sets the package provider to Exe if the the installer type is :wise" do
124
+ it "sets the package provider to Exe if the installer type is :wise" do
125
125
  allow(provider).to receive(:installer_type).and_return(:wise)
126
126
  expect(provider.package_provider).to be_a(Chef::Provider::Package::Windows::Exe)
127
127
  end
128
128
 
129
- it "sets the package provider to Exe if the the installer type is :installshield" do
129
+ it "sets the package provider to Exe if the installer type is :installshield" do
130
130
  allow(provider).to receive(:installer_type).and_return(:installshield)
131
131
  expect(provider.package_provider).to be_a(Chef::Provider::Package::Windows::Exe)
132
132
  end