puppet 6.21.0-x86-mingw32 → 6.24.0-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (217) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +5 -5
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +29 -23
  5. data/README.md +4 -4
  6. data/ext/osx/puppet.plist +2 -0
  7. data/ext/project_data.yaml +3 -2
  8. data/lib/puppet.rb +3 -3
  9. data/lib/puppet/application/agent.rb +12 -5
  10. data/lib/puppet/application/apply.rb +2 -1
  11. data/lib/puppet/application/device.rb +2 -1
  12. data/lib/puppet/application/filebucket.rb +1 -0
  13. data/lib/puppet/application/resource.rb +17 -3
  14. data/lib/puppet/application/script.rb +2 -1
  15. data/lib/puppet/application/ssl.rb +12 -0
  16. data/lib/puppet/configurer/downloader.rb +2 -1
  17. data/lib/puppet/defaults.rb +27 -5
  18. data/lib/puppet/environments.rb +26 -1
  19. data/lib/puppet/face/facts.rb +128 -30
  20. data/lib/puppet/face/help/action.erb +1 -0
  21. data/lib/puppet/face/help/face.erb +1 -0
  22. data/lib/puppet/face/node/clean.rb +11 -0
  23. data/lib/puppet/file_serving/fileset.rb +14 -2
  24. data/lib/puppet/file_system/file_impl.rb +1 -1
  25. data/lib/puppet/file_system/memory_file.rb +8 -1
  26. data/lib/puppet/file_system/windows.rb +4 -2
  27. data/lib/puppet/forge.rb +3 -3
  28. data/lib/puppet/functions/all.rb +1 -1
  29. data/lib/puppet/functions/camelcase.rb +1 -1
  30. data/lib/puppet/functions/capitalize.rb +2 -2
  31. data/lib/puppet/functions/downcase.rb +2 -2
  32. data/lib/puppet/functions/empty.rb +8 -0
  33. data/lib/puppet/functions/get.rb +5 -5
  34. data/lib/puppet/functions/group_by.rb +13 -5
  35. data/lib/puppet/functions/lest.rb +1 -1
  36. data/lib/puppet/functions/new.rb +100 -100
  37. data/lib/puppet/functions/partition.rb +12 -4
  38. data/lib/puppet/functions/require.rb +5 -5
  39. data/lib/puppet/functions/sort.rb +3 -3
  40. data/lib/puppet/functions/strftime.rb +1 -0
  41. data/lib/puppet/functions/tree_each.rb +7 -9
  42. data/lib/puppet/functions/type.rb +4 -4
  43. data/lib/puppet/functions/unwrap.rb +17 -2
  44. data/lib/puppet/functions/upcase.rb +2 -2
  45. data/lib/puppet/http/resolver/server_list.rb +15 -4
  46. data/lib/puppet/http/service/compiler.rb +69 -0
  47. data/lib/puppet/http/service/file_server.rb +2 -1
  48. data/lib/puppet/indirector/catalog/compiler.rb +1 -0
  49. data/lib/puppet/indirector/facts/facter.rb +24 -3
  50. data/lib/puppet/indirector/file_metadata/rest.rb +1 -0
  51. data/lib/puppet/indirector/resource/ral.rb +6 -1
  52. data/lib/puppet/interface/documentation.rb +1 -0
  53. data/lib/puppet/module_tool/applications/installer.rb +4 -0
  54. data/lib/puppet/module_tool/errors/shared.rb +17 -0
  55. data/lib/puppet/network/formats.rb +67 -0
  56. data/lib/puppet/network/http/factory.rb +4 -0
  57. data/lib/puppet/parser/functions/fqdn_rand.rb +14 -6
  58. data/lib/puppet/pops/types/p_sem_ver_type.rb +8 -2
  59. data/lib/puppet/pops/types/p_sensitive_type.rb +10 -0
  60. data/lib/puppet/pops/types/type_mismatch_describer.rb +1 -1
  61. data/lib/puppet/provider/exec/posix.rb +16 -4
  62. data/lib/puppet/provider/package/dnfmodule.rb +1 -1
  63. data/lib/puppet/provider/package/nim.rb +11 -6
  64. data/lib/puppet/provider/package/pip.rb +15 -3
  65. data/lib/puppet/provider/parsedfile.rb +3 -0
  66. data/lib/puppet/provider/service/systemd.rb +14 -4
  67. data/lib/puppet/provider/service/windows.rb +38 -0
  68. data/lib/puppet/provider/user/directoryservice.rb +25 -12
  69. data/lib/puppet/provider/user/useradd.rb +9 -2
  70. data/lib/puppet/reference/configuration.rb +1 -1
  71. data/lib/puppet/settings.rb +30 -7
  72. data/lib/puppet/settings/environment_conf.rb +1 -0
  73. data/lib/puppet/transaction/additional_resource_generator.rb +1 -1
  74. data/lib/puppet/type/exec.rb +16 -3
  75. data/lib/puppet/type/file.rb +19 -1
  76. data/lib/puppet/type/file/mode.rb +6 -0
  77. data/lib/puppet/type/file/selcontext.rb +1 -1
  78. data/lib/puppet/type/service.rb +18 -38
  79. data/lib/puppet/type/tidy.rb +22 -3
  80. data/lib/puppet/type/user.rb +38 -20
  81. data/lib/puppet/util/fact_dif.rb +36 -17
  82. data/lib/puppet/util/monkey_patches.rb +7 -0
  83. data/lib/puppet/util/selinux.rb +30 -4
  84. data/lib/puppet/util/symbolic_file_mode.rb +29 -17
  85. data/lib/puppet/util/windows/adsi.rb +46 -0
  86. data/lib/puppet/util/windows/api_types.rb +1 -1
  87. data/lib/puppet/util/windows/principal.rb +9 -2
  88. data/lib/puppet/util/windows/sid.rb +6 -2
  89. data/lib/puppet/version.rb +1 -1
  90. data/locales/puppet.pot +360 -280
  91. data/man/man5/puppet.conf.5 +279 -251
  92. data/man/man8/puppet-agent.8 +1 -1
  93. data/man/man8/puppet-apply.8 +1 -1
  94. data/man/man8/puppet-catalog.8 +9 -9
  95. data/man/man8/puppet-config.8 +1 -1
  96. data/man/man8/puppet-describe.8 +1 -1
  97. data/man/man8/puppet-device.8 +1 -1
  98. data/man/man8/puppet-doc.8 +1 -1
  99. data/man/man8/puppet-epp.8 +1 -1
  100. data/man/man8/puppet-facts.8 +65 -7
  101. data/man/man8/puppet-filebucket.8 +1 -1
  102. data/man/man8/puppet-generate.8 +1 -1
  103. data/man/man8/puppet-help.8 +1 -1
  104. data/man/man8/puppet-key.8 +7 -7
  105. data/man/man8/puppet-lookup.8 +1 -1
  106. data/man/man8/puppet-man.8 +1 -1
  107. data/man/man8/puppet-module.8 +1 -1
  108. data/man/man8/puppet-node.8 +5 -5
  109. data/man/man8/puppet-parser.8 +1 -1
  110. data/man/man8/puppet-plugin.8 +1 -1
  111. data/man/man8/puppet-report.8 +5 -5
  112. data/man/man8/puppet-resource.8 +1 -1
  113. data/man/man8/puppet-script.8 +1 -1
  114. data/man/man8/puppet-ssl.8 +5 -1
  115. data/man/man8/puppet-status.8 +4 -4
  116. data/man/man8/puppet.8 +2 -2
  117. data/spec/fixtures/ssl/127.0.0.1-key.pem +107 -57
  118. data/spec/fixtures/ssl/127.0.0.1.pem +52 -31
  119. data/spec/fixtures/ssl/bad-basic-constraints.pem +57 -35
  120. data/spec/fixtures/ssl/bad-int-basic-constraints.pem +57 -35
  121. data/spec/fixtures/ssl/ca.pem +57 -35
  122. data/spec/fixtures/ssl/crl.pem +28 -18
  123. data/spec/fixtures/ssl/ec-key.pem +11 -11
  124. data/spec/fixtures/ssl/ec.pem +33 -24
  125. data/spec/fixtures/ssl/encrypted-ec-key.pem +12 -12
  126. data/spec/fixtures/ssl/encrypted-key.pem +108 -58
  127. data/spec/fixtures/ssl/intermediate-agent-crl.pem +28 -19
  128. data/spec/fixtures/ssl/intermediate-agent.pem +57 -36
  129. data/spec/fixtures/ssl/intermediate-crl.pem +31 -21
  130. data/spec/fixtures/ssl/intermediate.pem +57 -36
  131. data/spec/fixtures/ssl/oid-key.pem +117 -0
  132. data/spec/fixtures/ssl/oid.pem +69 -0
  133. data/spec/fixtures/ssl/pluto-key.pem +107 -57
  134. data/spec/fixtures/ssl/pluto.pem +52 -30
  135. data/spec/fixtures/ssl/request-key.pem +107 -57
  136. data/spec/fixtures/ssl/request.pem +47 -26
  137. data/spec/fixtures/ssl/revoked-key.pem +107 -57
  138. data/spec/fixtures/ssl/revoked.pem +52 -30
  139. data/spec/fixtures/ssl/signed-key.pem +107 -57
  140. data/spec/fixtures/ssl/signed.pem +52 -30
  141. data/spec/fixtures/ssl/tampered-cert.pem +52 -30
  142. data/spec/fixtures/ssl/tampered-csr.pem +47 -26
  143. data/spec/fixtures/ssl/trusted_oid_mapping.yaml +5 -0
  144. data/spec/fixtures/ssl/unknown-127.0.0.1-key.pem +107 -57
  145. data/spec/fixtures/ssl/unknown-127.0.0.1.pem +50 -29
  146. data/spec/fixtures/ssl/unknown-ca-key.pem +107 -57
  147. data/spec/fixtures/ssl/unknown-ca.pem +55 -33
  148. data/spec/fixtures/unit/provider/service/systemd/list_unit_files_services_vendor_preset +9 -0
  149. data/spec/integration/application/filebucket_spec.rb +11 -0
  150. data/spec/integration/application/module_spec.rb +21 -0
  151. data/spec/integration/application/plugin_spec.rb +1 -1
  152. data/spec/integration/application/resource_spec.rb +64 -0
  153. data/spec/integration/application/ssl_spec.rb +20 -0
  154. data/spec/integration/environments/settings_interpolation_spec.rb +0 -4
  155. data/spec/integration/http/client_spec.rb +12 -0
  156. data/spec/integration/indirector/direct_file_server_spec.rb +1 -3
  157. data/spec/integration/indirector/facts/facter_spec.rb +90 -36
  158. data/spec/integration/type/exec_spec.rb +70 -45
  159. data/spec/integration/util/windows/adsi_spec.rb +18 -0
  160. data/spec/integration/util/windows/principal_spec.rb +21 -0
  161. data/spec/integration/util/windows/registry_spec.rb +6 -0
  162. data/spec/lib/puppet/test_ca.rb +7 -2
  163. data/spec/lib/puppet_spec/settings.rb +1 -0
  164. data/spec/spec_helper.rb +11 -1
  165. data/spec/unit/application/agent_spec.rb +7 -2
  166. data/spec/unit/application/facts_spec.rb +482 -3
  167. data/spec/unit/application/ssl_spec.rb +23 -0
  168. data/spec/unit/configurer/downloader_spec.rb +6 -0
  169. data/spec/unit/configurer_spec.rb +23 -0
  170. data/spec/unit/defaults_spec.rb +16 -0
  171. data/spec/unit/environments_spec.rb +199 -88
  172. data/spec/unit/face/facts_spec.rb +4 -0
  173. data/spec/unit/file_serving/fileset_spec.rb +60 -0
  174. data/spec/unit/file_system_spec.rb +15 -0
  175. data/spec/unit/functions/assert_type_spec.rb +1 -1
  176. data/spec/unit/functions/empty_spec.rb +10 -0
  177. data/spec/unit/functions/unwrap_spec.rb +8 -0
  178. data/spec/unit/functions4_spec.rb +2 -2
  179. data/spec/unit/gettext/config_spec.rb +12 -0
  180. data/spec/unit/http/service/compiler_spec.rb +123 -0
  181. data/spec/unit/indirector/catalog/compiler_spec.rb +14 -10
  182. data/spec/unit/indirector/facts/facter_spec.rb +95 -0
  183. data/spec/unit/indirector/resource/ral_spec.rb +40 -75
  184. data/spec/unit/module_tool/applications/installer_spec.rb +12 -0
  185. data/spec/unit/network/formats_spec.rb +41 -0
  186. data/spec/unit/network/http/factory_spec.rb +19 -0
  187. data/spec/unit/parser/functions/fqdn_rand_spec.rb +15 -1
  188. data/spec/unit/parser/templatewrapper_spec.rb +12 -2
  189. data/spec/unit/pops/types/p_sem_ver_type_spec.rb +18 -0
  190. data/spec/unit/pops/types/p_sensitive_type_spec.rb +18 -0
  191. data/spec/unit/provider/package/dnfmodule_spec.rb +10 -1
  192. data/spec/unit/provider/package/nim_spec.rb +42 -0
  193. data/spec/unit/provider/package/pip_spec.rb +37 -0
  194. data/spec/unit/provider/parsedfile_spec.rb +10 -0
  195. data/spec/unit/provider/service/init_spec.rb +1 -0
  196. data/spec/unit/provider/service/openwrt_spec.rb +3 -1
  197. data/spec/unit/provider/service/systemd_spec.rb +53 -8
  198. data/spec/unit/provider/service/windows_spec.rb +202 -0
  199. data/spec/unit/provider/user/directoryservice_spec.rb +67 -35
  200. data/spec/unit/provider/user/useradd_spec.rb +21 -6
  201. data/spec/unit/resource/catalog_spec.rb +1 -1
  202. data/spec/unit/settings_spec.rb +97 -56
  203. data/spec/unit/ssl/state_machine_spec.rb +19 -5
  204. data/spec/unit/transaction/additional_resource_generator_spec.rb +0 -2
  205. data/spec/unit/transaction_spec.rb +18 -20
  206. data/spec/unit/type/exec_spec.rb +76 -29
  207. data/spec/unit/type/file/selinux_spec.rb +3 -3
  208. data/spec/unit/type/file/source_spec.rb +4 -4
  209. data/spec/unit/type/service_spec.rb +59 -188
  210. data/spec/unit/type/tidy_spec.rb +24 -7
  211. data/spec/unit/type/user_spec.rb +45 -0
  212. data/spec/unit/util/selinux_spec.rb +87 -16
  213. data/spec/unit/util/windows/sid_spec.rb +41 -0
  214. data/tasks/generate_cert_fixtures.rake +12 -3
  215. metadata +24 -9
  216. data/spec/lib/matchers/include.rb +0 -27
  217. data/spec/lib/matchers/include_spec.rb +0 -32
@@ -183,6 +183,73 @@ Puppet::Network::FormatHandler.create(:console,
183
183
  end
184
184
  end
185
185
 
186
+ Puppet::Network::FormatHandler.create(:flat,
187
+ :mime => 'text/x-flat-text',
188
+ :weight => 0) do
189
+
190
+ def flatten_hash(hash)
191
+ hash.each_with_object({}) do |(k, v), h|
192
+ if v.is_a? Hash
193
+ flatten_hash(v).map do |h_k, h_v|
194
+ h["#{k}.#{h_k}"] = h_v
195
+ end
196
+ elsif v.is_a? Array
197
+ v.each_with_index do |el, i|
198
+ if el.is_a? Hash
199
+ flatten_hash(el).map do |el_k, el_v|
200
+ h["#{k}.#{i}.#{el_k}"] = el_v
201
+ end
202
+ else
203
+ h["#{k}.#{i}"] = el
204
+ end
205
+ end
206
+ else
207
+ h[k] = v
208
+ end
209
+ end
210
+ end
211
+
212
+ def flatten_array(array)
213
+ a={}
214
+ array.each_with_index do |el, i|
215
+ if el.is_a? Hash
216
+ flatten_hash(el).map do |el_k, el_v|
217
+ a["#{i}.#{el_k}"] = el_v
218
+ end
219
+ else
220
+ a["#{i}"] = el
221
+ end
222
+ end
223
+ a
224
+ end
225
+
226
+ def construct_output(data)
227
+ output = ''
228
+ data.each do |key, value|
229
+ output << "#{key}=#{value}"
230
+ output << "\n"
231
+ end
232
+ output
233
+ end
234
+
235
+ def render(datum)
236
+ return datum if datum.is_a?(String) || datum.is_a?(Numeric)
237
+ # Simple hash
238
+ if datum.is_a?(Hash)
239
+ data = flatten_hash(datum)
240
+ return construct_output(data)
241
+ elsif datum.is_a?(Array)
242
+ data = flatten_array(datum)
243
+ return construct_output(data)
244
+ end
245
+ Puppet::Util::Json.dump(datum, :pretty => true, :quirks_mode => true)
246
+ end
247
+ def render_multiple(data)
248
+ data.collect(&:render).join("\n")
249
+ end
250
+ end
251
+
252
+
186
253
  Puppet::Network::FormatHandler.create(:rich_data_json, mime: 'application/vnd.puppet.rich+json', charset: Encoding::UTF_8, weight: 30) do
187
254
  def intern(klass, text)
188
255
  Puppet.override({:rich_data => true}) do
@@ -27,6 +27,10 @@ class Puppet::Network::HTTP::Factory
27
27
 
28
28
  http = Puppet::Util::HttpProxy.proxy(URI(site.addr))
29
29
  http.use_ssl = site.use_ssl?
30
+ if site.use_ssl?
31
+ http.min_version = OpenSSL::SSL::TLS1_VERSION if http.respond_to?(:min_version)
32
+ http.ciphers = Puppet[:ciphers]
33
+ end
30
34
  http.read_timeout = Puppet[:http_read_timeout]
31
35
  http.open_timeout = Puppet[:http_connect_timeout]
32
36
  http.keep_alive_timeout = KEEP_ALIVE_TIMEOUT if http.respond_to?(:keep_alive_timeout=)
@@ -2,13 +2,16 @@ require 'digest/md5'
2
2
  require 'digest/sha2'
3
3
 
4
4
  Puppet::Parser::Functions::newfunction(:fqdn_rand, :arity => -2, :type => :rvalue, :doc =>
5
- "Usage: `fqdn_rand(MAX, [SEED])`. MAX is required and must be a positive
6
- integer; SEED is optional and may be any number or string.
5
+ "Usage: `fqdn_rand(MAX, [SEED], [DOWNCASE])`. MAX is required and must be a positive
6
+ integer; SEED is optional and may be any number or string; DOWNCASE is optional
7
+ and should be a boolean true or false.
7
8
 
8
9
  Generates a random Integer number greater than or equal to 0 and less than MAX,
9
10
  combining the `$fqdn` fact and the value of SEED for repeatable randomness.
10
11
  (That is, each node will get a different random number from this function, but
11
- a given node's result will be the same every time unless its hostname changes.)
12
+ a given node's result will be the same every time unless its hostname changes.) If
13
+ DOWNCASE is true, then the `fqdn` fact will be downcased when computing the value
14
+ so that the result is not sensitive to the case of the `fqdn` fact.
12
15
 
13
16
  This function is usually used for spacing out runs of resource-intensive cron
14
17
  tasks that run on many nodes, which could cause a thundering herd or degrade
@@ -17,7 +20,12 @@ Puppet::Parser::Functions::newfunction(:fqdn_rand, :arity => -2, :type => :rvalu
17
20
  node. (For example, `fqdn_rand(30)`, `fqdn_rand(30, 'expensive job 1')`, and
18
21
  `fqdn_rand(30, 'expensive job 2')` will produce totally different numbers.)") do |args|
19
22
  max = args.shift.to_i
20
-
23
+ initial_seed = args.shift
24
+ downcase = !!args.shift
25
+
26
+ fqdn = self['::fqdn']
27
+ fqdn = fqdn.downcase if downcase
28
+
21
29
  # Puppet 5.4's fqdn_rand function produces a different value than earlier versions
22
30
  # for the same set of inputs.
23
31
  # This causes problems because the values are often written into service configuration files.
@@ -27,9 +35,9 @@ Puppet::Parser::Functions::newfunction(:fqdn_rand, :arity => -2, :type => :rvalu
27
35
  # when running on a non-FIPS enabled platform and only using SHA256 on FIPS enabled
28
36
  # platforms.
29
37
  if Puppet::Util::Platform.fips_enabled?
30
- seed = Digest::SHA256.hexdigest([self['::fqdn'],max,args].join(':')).hex
38
+ seed = Digest::SHA256.hexdigest([fqdn,max,initial_seed].join(':')).hex
31
39
  else
32
- seed = Digest::MD5.hexdigest([self['::fqdn'],max,args].join(':')).hex
40
+ seed = Digest::MD5.hexdigest([fqdn,max,initial_seed].join(':')).hex
33
41
  end
34
42
 
35
43
  Puppet::Util.deterministic_rand_int(seed,max)
@@ -95,16 +95,22 @@ class PSemVerType < PScalarType
95
95
  end
96
96
 
97
97
  def from_args(major, minor, patch, prerelease = nil, build = nil)
98
- SemanticPuppet::Version.new(major, minor, patch, prerelease, build)
98
+ SemanticPuppet::Version.new(major, minor, patch, to_array(prerelease), to_array(build))
99
99
  end
100
100
 
101
101
  def from_hash(hash)
102
- SemanticPuppet::Version.new(hash['major'], hash['minor'], hash['patch'], hash['prerelease'], hash['build'])
102
+ SemanticPuppet::Version.new(hash['major'], hash['minor'], hash['patch'], to_array(hash['prerelease']), to_array(hash['build']))
103
103
  end
104
104
 
105
105
  def on_error(str)
106
106
  _("The string '%{str}' cannot be converted to a SemVer") % { str: str }
107
107
  end
108
+
109
+ private
110
+
111
+ def to_array(component)
112
+ component ? [component] : nil
113
+ end
108
114
  end
109
115
  end
110
116
 
@@ -24,6 +24,16 @@ class PSensitiveType < PTypeWithContainedType
24
24
  def inspect
25
25
  "#<#{self}>"
26
26
  end
27
+
28
+ def hash
29
+ @value.hash
30
+ end
31
+
32
+ def ==(other)
33
+ other.is_a?(Sensitive) &&
34
+ other.hash == hash
35
+ end
36
+ alias eql? ==
27
37
  end
28
38
 
29
39
  def self.register_ptype(loader, ir)
@@ -640,7 +640,7 @@ module Types
640
640
  result = ["#{label} expects (#{signature_string(sig)})"]
641
641
  result.concat(error_arrays[0].map { |e| " rejected:#{e.chop_path(0).format}" })
642
642
  else
643
- result = ["#{label} expects one of:"]
643
+ result = ["The function #{label} was called with arguments it does not accept. It expects one of:"]
644
644
  signatures.each_with_index do |sg, index|
645
645
  result << " (#{signature_string(sg)})"
646
646
  result.concat(error_arrays[index].map { |e| " rejected:#{e.chop_path(0).format}" })
@@ -6,10 +6,22 @@ Puppet::Type.type(:exec).provide :posix, :parent => Puppet::Provider::Exec do
6
6
  defaultfor :feature => :posix
7
7
 
8
8
  desc <<-EOT
9
- Executes external binaries directly, without passing through a shell or
10
- performing any interpolation. This is a safer and more predictable way
11
- to execute most commands, but prevents the use of globbing and shell
12
- built-ins (including control logic like "for" and "if" statements).
9
+ Executes external binaries by invoking Ruby's `Kernel.exec`.
10
+ When the command is a string, it will be executed directly,
11
+ without a shell, if it follows these rules:
12
+ - no meta characters
13
+ - no shell reserved word and no special built-in
14
+
15
+ When the command is an Array of Strings, passed as `[cmdname, arg1, ...]`
16
+ it will be executed directly(the first element is taken as a command name
17
+ and the rest are passed as parameters to command with no shell expansion)
18
+ This is a safer and more predictable way to execute most commands,
19
+ but prevents the use of globbing and shell built-ins (including control
20
+ logic like "for" and "if" statements).
21
+
22
+ If the use of globbing and shell built-ins is desired, please check
23
+ the `shell` provider
24
+
13
25
  EOT
14
26
 
15
27
  # Verify that we have the executable
@@ -93,7 +93,7 @@ Puppet::Type.type(:package).provide :dnfmodule, :parent => :dnf do
93
93
  # module has no default profile and no profile was requested, so just enable the stream
94
94
  # DNF versions prior to 4.2.8 do not need this workaround
95
95
  # see https://bugzilla.redhat.com/show_bug.cgi?id=1669527
96
- if @resource[:flavor] == nil && e.message =~ /^missing groups or modules: #{Regexp.quote(@resource[:name])}$/
96
+ if @resource[:flavor] == nil && e.message =~ /^(?:missing|broken) groups or modules: #{Regexp.quote(@resource[:name])}$/
97
97
  enable(args)
98
98
  else
99
99
  raise
@@ -154,20 +154,25 @@ Puppet::Type.type(:package).provide :nim, :parent => :aix, :source => :aix do
154
154
  # I spent a lot of time trying to figure out a solution that didn't
155
155
  # require parsing the `nimclient -o showres` output and was unable to
156
156
  # do so.
157
- self::HEADER_LINE_REGEX = /^([^\s]+)\s+[^@]+@@(I|R):(\1)\s+[^\s]+$/
158
- self::PACKAGE_LINE_REGEX = /^.*@@(I|R):(.*)$/
159
- self::RPM_PACKAGE_REGEX = /^(.*)-(.*-\d+) \2$/
157
+ self::HEADER_LINE_REGEX = /^([^\s]+)\s+[^@]+@@(I|R|S):(\1)\s+[^\s]+$/
158
+ self::PACKAGE_LINE_REGEX = /^.*@@(I|R|S):(.*)$/
159
+ self::RPM_PACKAGE_REGEX = /^(.*)-(.*-\d+\w*) \2$/
160
160
  self::INSTALLP_PACKAGE_REGEX = /^(.*) (.*)$/
161
161
 
162
162
  # Here is some sample output that shows what the above regexes will be up
163
163
  # against:
164
- # FOR AN INSTALLP PACKAGE:
164
+ # FOR AN INSTALLP(bff) PACKAGE:
165
165
  #
166
166
  # mypackage.foo ALL @@I:mypackage.foo _all_filesets
167
- # @ 1.2.3.1 MyPackage Runtime Environment @@I:mypackage.foo 1.2.3.1
168
167
  # + 1.2.3.4 MyPackage Runtime Environment @@I:mypackage.foo 1.2.3.4
169
168
  # + 1.2.3.8 MyPackage Runtime Environment @@I:mypackage.foo 1.2.3.8
170
169
  #
170
+ # FOR AN INSTALLP(bff) PACKAGE with security update:
171
+ #
172
+ # bos.net ALL @@S:bos.net _all_filesets
173
+ # + 7.2.0.1 TCP/IP ntp Applications @@S:bos.net.tcp.ntp 7.2.0.1
174
+ # + 7.2.0.2 TCP/IP ntp Applications @@S:bos.net.tcp.ntp 7.2.0.2
175
+ #
171
176
  # FOR AN RPM PACKAGE:
172
177
  #
173
178
  # mypackage.foo ALL @@R:mypackage.foo _all_filesets
@@ -243,7 +248,7 @@ Puppet::Type.type(:package).provide :nim, :parent => :aix, :source => :aix do
243
248
  package_string = match.captures[1]
244
249
 
245
250
  case package_type_flag
246
- when "I"
251
+ when "I","S"
247
252
  parse_installp_package_string(package_string)
248
253
  when "R"
249
254
  parse_rpm_package_string(package_string)
@@ -127,7 +127,7 @@ Puppet::Type.type(:package).provide :pip, :parent => ::Puppet::Provider::Package
127
127
  if self.class.compare_pip_versions(command_version, '1.5.4') == -1
128
128
  available_versions_with_old_pip.last
129
129
  else
130
- available_versions_with_new_pip.last
130
+ available_versions_with_new_pip(command_version).last
131
131
  end
132
132
  end
133
133
 
@@ -150,15 +150,17 @@ Puppet::Type.type(:package).provide :pip, :parent => ::Puppet::Provider::Package
150
150
  if self.class.compare_pip_versions(command_version, '1.5.4') == -1
151
151
  available_versions_with_old_pip
152
152
  else
153
- available_versions_with_new_pip
153
+ available_versions_with_new_pip(command_version)
154
154
  end
155
155
  end
156
156
 
157
- def available_versions_with_new_pip
157
+ def available_versions_with_new_pip(command_version)
158
158
  command = resource_or_provider_command
159
159
  self.class.validate_command(command)
160
160
 
161
161
  command_and_options = [self.class.quote(command), 'install', "#{@resource[:name]}==versionplease"]
162
+ extra_arg = list_extra_flags(command_version)
163
+ command_and_options << extra_arg if extra_arg
162
164
  command_and_options << install_options if @resource[:install_options]
163
165
  execpipe command_and_options do |process|
164
166
  process.collect do |line|
@@ -329,4 +331,14 @@ Puppet::Type.type(:package).provide :pip, :parent => ::Puppet::Provider::Package
329
331
  path
330
332
  end
331
333
  end
334
+
335
+ private
336
+
337
+ def list_extra_flags(command_version)
338
+ klass = self.class
339
+ if klass.compare_pip_versions(command_version, '20.2.4') == 1 &&
340
+ klass.compare_pip_versions(command_version, '21.1') == -1
341
+ '--use-deprecated=legacy-resolver'
342
+ end
343
+ end
332
344
  end
@@ -280,6 +280,9 @@ class Puppet::Provider::ParsedFile < Puppet::Provider
280
280
  def self.prefetch_target(target)
281
281
  begin
282
282
  target_records = retrieve(target)
283
+ unless target_records
284
+ raise Puppet::DevError, _("Prefetching %{target} for provider %{name} returned nil") % { target: target, name: self.name }
285
+ end
283
286
  rescue Puppet::Util::FileType::FileReadError => detail
284
287
  if @raise_prefetch_errors
285
288
  # We will raise an error later in flush_target. This way,
@@ -30,7 +30,7 @@ Puppet::Type.type(:service).provide :systemd, :parent => :base do
30
30
  def self.instances
31
31
  i = []
32
32
  output = systemctl('list-unit-files', '--type', 'service', '--full', '--all', '--no-pager')
33
- output.scan(/^(\S+)\s+(disabled|enabled|masked|indirect|bad|static)\s*$/i).each do |m|
33
+ output.scan(/^(\S+)\s+(disabled|enabled|masked|indirect|bad|static)\s*([^-]\S+)?\s*$/i).each do |m|
34
34
  Puppet.debug("#{m[0]} marked as bad by `systemctl`. It is recommended to be further checked.") if m[1] == "bad"
35
35
  i << new(:name => m[0])
36
36
  end
@@ -45,8 +45,13 @@ Puppet::Type.type(:service).provide :systemd, :parent => :base do
45
45
  def enabled_insync?(current)
46
46
  case cached_enabled?[:output]
47
47
  when 'static'
48
- Puppet.debug("Unable to enable or disable static service #{@resource[:name]}")
49
- return true
48
+ # masking static services is OK, but enabling/disabling them is not
49
+ if @resource[:enable] == :mask
50
+ current == @resource[:enable]
51
+ else
52
+ Puppet.debug("Unable to enable or disable static service #{@resource[:name]}")
53
+ return true
54
+ end
50
55
  when 'indirect'
51
56
  Puppet.debug("Service #{@resource[:name]} is in 'indirect' state and cannot be enabled/disabled")
52
57
  return true
@@ -159,10 +164,15 @@ Puppet::Type.type(:service).provide :systemd, :parent => :base do
159
164
  end
160
165
 
161
166
  def mask
162
- self.disable
167
+ disable if exist?
163
168
  systemctl_change_enable(:mask)
164
169
  end
165
170
 
171
+ def exist?
172
+ result = execute([command(:systemctl), 'cat', '--', @resource[:name]], :failonfail => false)
173
+ result.exitstatus == 0
174
+ end
175
+
166
176
  def unmask
167
177
  systemctl_change_enable(:unmask)
168
178
  end
@@ -128,17 +128,55 @@ Puppet::Type.type(:service).provide :windows, :parent => :service do
128
128
  services
129
129
  end
130
130
 
131
+ def logonaccount_insync?(current)
132
+ @normalized_logon_account ||= normalize_logonaccount
133
+ @resource[:logonaccount] = @normalized_logon_account
134
+
135
+ insync = @resource[:logonaccount] == current
136
+ self.logonpassword = @resource[:logonpassword] if insync
137
+ insync
138
+ end
139
+
131
140
  def logonaccount
132
141
  return unless Puppet::Util::Windows::Service.exists?(@resource[:name])
133
142
  Puppet::Util::Windows::Service.logon_account(@resource[:name])
134
143
  end
135
144
 
136
145
  def logonaccount=(value)
146
+ validate_logon_credentials
137
147
  Puppet::Util::Windows::Service.set_startup_configuration(@resource[:name], options: {logon_account: value, logon_password: @resource[:logonpassword]})
138
148
  restart if @resource[:ensure] == :running && [:running, :paused].include?(status)
139
149
  end
140
150
 
141
151
  def logonpassword=(value)
152
+ validate_logon_credentials
142
153
  Puppet::Util::Windows::Service.set_startup_configuration(@resource[:name], options: {logon_password: value})
143
154
  end
155
+
156
+ private
157
+
158
+ def normalize_logonaccount
159
+ logon_account = @resource[:logonaccount].sub(/^\.\\/, "#{Puppet::Util::Windows::ADSI.computer_name}\\")
160
+ return 'LocalSystem' if Puppet::Util::Windows::User::localsystem?(logon_account)
161
+
162
+ @logonaccount_information ||= Puppet::Util::Windows::SID.name_to_principal(logon_account)
163
+ return logon_account unless @logonaccount_information
164
+ return ".\\#{@logonaccount_information.account}" if @logonaccount_information.domain == Puppet::Util::Windows::ADSI.computer_name
165
+ @logonaccount_information.domain_account
166
+ end
167
+
168
+ def validate_logon_credentials
169
+ unless Puppet::Util::Windows::User::localsystem?(@normalized_logon_account)
170
+ raise Puppet::Error.new("\"#{@normalized_logon_account}\" is not a valid account") unless @logonaccount_information && [:SidTypeUser, :SidTypeWellKnownGroup].include?(@logonaccount_information.account_type)
171
+
172
+ user_rights = Puppet::Util::Windows::User::get_rights(@logonaccount_information.domain_account) unless Puppet::Util::Windows::User::default_system_account?(@normalized_logon_account)
173
+ raise Puppet::Error.new("\"#{@normalized_logon_account}\" has the 'Log On As A Service' right set to denied.") if user_rights =~ /SeDenyServiceLogonRight/
174
+ raise Puppet::Error.new("\"#{@normalized_logon_account}\" is missing the 'Log On As A Service' right.") unless user_rights.nil? || user_rights =~ /SeServiceLogonRight/
175
+ end
176
+
177
+ is_a_predefined_local_account = Puppet::Util::Windows::User::default_system_account?(@normalized_logon_account) || @normalized_logon_account == 'LocalSystem'
178
+ account_info = @normalized_logon_account.split("\\")
179
+ able_to_logon = Puppet::Util::Windows::User.password_is?(account_info[1], @resource[:logonpassword], account_info[0]) unless is_a_predefined_local_account
180
+ raise Puppet::Error.new("The given password is invalid for user '#{@normalized_logon_account}'.") unless is_a_predefined_local_account || able_to_logon
181
+ end
144
182
  end
@@ -435,7 +435,7 @@ Puppet::Type.type(:user).provide :directoryservice do
435
435
  ['home', 'uid', 'gid', 'comment', 'shell'].each do |setter_method|
436
436
  define_method("#{setter_method}=") do |value|
437
437
  if @property_hash[setter_method.intern]
438
- if self.class.get_os_version.split('.').last.to_i >= 14 && %w(home uid).include?(setter_method)
438
+ if %w(home uid).include?(setter_method)
439
439
  raise Puppet::Error, "OS X version #{self.class.get_os_version} does not allow changing #{setter_method} using puppet"
440
440
  end
441
441
  begin
@@ -536,6 +536,14 @@ Puppet::Type.type(:user).provide :directoryservice do
536
536
  if (shadow_hash_data.class == Hash) && (shadow_hash_data.has_key?('SALTED-SHA512'))
537
537
  shadow_hash_data.delete('SALTED-SHA512')
538
538
  end
539
+
540
+ # Starting with macOS 11 Big Sur, the AuthenticationAuthority field
541
+ # could be missing entirely and without it the managed user cannot log in
542
+ if needs_sha512_pbkdf2_authentication_authority_to_be_added?(users_plist)
543
+ Puppet.debug("Adding 'SALTED-SHA512-PBKDF2' AuthenticationAuthority key for ShadowHash to user '#{@resource.name}'")
544
+ merge_attribute_with_dscl('Users', @resource.name, 'AuthenticationAuthority', ERB::Util.html_escape(SHA512_PBKDF2_AUTHENTICATION_AUTHORITY))
545
+ end
546
+
539
547
  set_salted_pbkdf2(users_plist, shadow_hash_data, 'entropy', value)
540
548
  end
541
549
  end
@@ -562,6 +570,17 @@ Puppet::Type.type(:user).provide :directoryservice do
562
570
  end
563
571
  end
564
572
 
573
+ # This method will check if authentication_authority key of a user's plist
574
+ # needs SALTED_SHA512_PBKDF2 to be added. This is a valid case for macOS 11 (Big Sur)
575
+ # where users created with `dscl` started to have this field missing
576
+ def needs_sha512_pbkdf2_authentication_authority_to_be_added?(users_plist)
577
+ authority = users_plist['authentication_authority']
578
+ return false if Puppet::Util::Package.versioncmp(self.class.get_os_version, '11.0.0') < 0 && authority && authority.include?(SHA512_PBKDF2_AUTHENTICATION_AUTHORITY)
579
+
580
+ Puppet.debug("User '#{@resource.name}' is missing the 'SALTED-SHA512-PBKDF2' AuthenticationAuthority key for ShadowHash")
581
+ true
582
+ end
583
+
565
584
  # This method will embed the binary plist data comprising the user's
566
585
  # password hash (and Salt/Iterations value if the OS is 10.8 or greater)
567
586
  # into the ShadowHashData key of the user's plist.
@@ -572,11 +591,7 @@ Puppet::Type.type(:user).provide :directoryservice do
572
591
  else
573
592
  users_plist['ShadowHashData'] = [binary_plist]
574
593
  end
575
- if Puppet::Util::Package.versioncmp(self.class.get_os_version, '10.15') < 0
576
- write_users_plist_to_disk(users_plist)
577
- else
578
- write_and_import_shadow_hash_data(users_plist['ShadowHashData'].first)
579
- end
594
+ write_and_import_shadow_hash_data(users_plist['ShadowHashData'].first)
580
595
  end
581
596
 
582
597
  # This method writes the ShadowHashData plist in a temporary file,
@@ -652,12 +667,6 @@ Puppet::Type.type(:user).provide :directoryservice do
652
667
  set_shadow_hash_data(users_plist, binary_plist)
653
668
  end
654
669
 
655
- # This method will accept a plist in XML format, save it to disk, convert
656
- # the plist to a binary format, and flush the dscl cache.
657
- def write_users_plist_to_disk(users_plist)
658
- Puppet::Util::Plist.write_plist_file(users_plist, "#{users_plist_dir}/#{@resource.name}.plist", :binary)
659
- end
660
-
661
670
  # This is a simple wrapper method for writing values to a file.
662
671
  def write_to_file(filename, value)
663
672
  Puppet.deprecation_warning("Puppet::Type.type(:user).provider(:directoryservice).write_to_file is deprecated and will be removed in Puppet 5.")
@@ -667,4 +676,8 @@ Puppet::Type.type(:user).provide :directoryservice do
667
676
  raise Puppet::Error, "Could not write to file #{filename}: #{detail}", detail.backtrace
668
677
  end
669
678
  end
679
+
680
+ private
681
+
682
+ SHA512_PBKDF2_AUTHENTICATION_AUTHORITY = ';ShadowHash;HASHLIST:<SALTED-SHA512-PBKDF2,SRP-RFC5054-4096-SHA512-PBKDF2>'
670
683
  end