puppet 6.25.1 → 6.28.0

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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/CODEOWNERS +1 -1
  3. data/Gemfile +2 -2
  4. data/Gemfile.lock +101 -34
  5. data/lib/puppet/agent.rb +47 -11
  6. data/lib/puppet/application/agent.rb +2 -12
  7. data/lib/puppet/application/lookup.rb +74 -24
  8. data/lib/puppet/concurrent/thread_local_singleton.rb +5 -3
  9. data/lib/puppet/configurer.rb +8 -14
  10. data/lib/puppet/defaults.rb +13 -3
  11. data/lib/puppet/face/generate.rb +2 -0
  12. data/lib/puppet/file_serving/metadata.rb +3 -0
  13. data/lib/puppet/file_system/file_impl.rb +7 -7
  14. data/lib/puppet/file_system/jruby.rb +1 -1
  15. data/lib/puppet/file_system/windows.rb +4 -4
  16. data/lib/puppet/file_system.rb +1 -1
  17. data/lib/puppet/functions/next.rb +18 -1
  18. data/lib/puppet/functions/tree_each.rb +0 -1
  19. data/lib/puppet/functions/versioncmp.rb +6 -2
  20. data/lib/puppet/generate/type.rb +9 -0
  21. data/lib/puppet/http/client.rb +22 -2
  22. data/lib/puppet/node.rb +1 -1
  23. data/lib/puppet/pops/parser/code_merger.rb +4 -4
  24. data/lib/puppet/pops/parser/egrammar.ra +2 -0
  25. data/lib/puppet/pops/parser/eparser.rb +813 -794
  26. data/lib/puppet/pops/serialization/to_data_converter.rb +6 -18
  27. data/lib/puppet/provider/package/puppetserver_gem.rb +7 -16
  28. data/lib/puppet/provider/package/windows/exe_package.rb +30 -1
  29. data/lib/puppet/provider/package/windows/package.rb +2 -1
  30. data/lib/puppet/provider/package/windows.rb +14 -1
  31. data/lib/puppet/provider/service/init.rb +5 -4
  32. data/lib/puppet/provider/user/directoryservice.rb +5 -0
  33. data/lib/puppet/ssl/ssl_provider.rb +75 -19
  34. data/lib/puppet/ssl/state_machine.rb +13 -17
  35. data/lib/puppet/ssl/verifier.rb +6 -0
  36. data/lib/puppet/transaction/persistence.rb +22 -12
  37. data/lib/puppet/type/exec.rb +1 -1
  38. data/lib/puppet/type/file/data_sync.rb +1 -1
  39. data/lib/puppet/type/user.rb +43 -38
  40. data/lib/puppet/util/json.rb +17 -0
  41. data/lib/puppet/util/log.rb +7 -2
  42. data/lib/puppet/util/monkey_patches.rb +6 -2
  43. data/lib/puppet/util/package.rb +25 -16
  44. data/lib/puppet/util/yaml.rb +21 -2
  45. data/lib/puppet/util.rb +1 -2
  46. data/lib/puppet/version.rb +1 -1
  47. data/lib/puppet.rb +2 -14
  48. data/locales/puppet.pot +5 -10454
  49. data/man/man5/puppet.conf.5 +21 -2
  50. data/man/man8/puppet-agent.8 +1 -1
  51. data/man/man8/puppet-apply.8 +1 -1
  52. data/man/man8/puppet-catalog.8 +1 -1
  53. data/man/man8/puppet-config.8 +1 -1
  54. data/man/man8/puppet-describe.8 +1 -1
  55. data/man/man8/puppet-device.8 +1 -1
  56. data/man/man8/puppet-doc.8 +1 -1
  57. data/man/man8/puppet-epp.8 +1 -1
  58. data/man/man8/puppet-facts.8 +1 -1
  59. data/man/man8/puppet-filebucket.8 +1 -1
  60. data/man/man8/puppet-generate.8 +1 -1
  61. data/man/man8/puppet-help.8 +1 -1
  62. data/man/man8/puppet-key.8 +1 -1
  63. data/man/man8/puppet-lookup.8 +9 -6
  64. data/man/man8/puppet-man.8 +1 -1
  65. data/man/man8/puppet-module.8 +1 -1
  66. data/man/man8/puppet-node.8 +1 -1
  67. data/man/man8/puppet-parser.8 +1 -1
  68. data/man/man8/puppet-plugin.8 +1 -1
  69. data/man/man8/puppet-report.8 +1 -1
  70. data/man/man8/puppet-resource.8 +1 -1
  71. data/man/man8/puppet-script.8 +1 -1
  72. data/man/man8/puppet-ssl.8 +1 -1
  73. data/man/man8/puppet-status.8 +1 -1
  74. data/man/man8/puppet.8 +2 -2
  75. data/spec/fixtures/unit/forge/bacula.json +1 -1
  76. data/spec/integration/application/agent_spec.rb +108 -0
  77. data/spec/integration/application/lookup_spec.rb +81 -50
  78. data/spec/integration/application/resource_spec.rb +6 -2
  79. data/spec/integration/http/client_spec.rb +51 -4
  80. data/spec/lib/puppet_spec/https.rb +1 -1
  81. data/spec/lib/puppet_spec/puppetserver.rb +39 -2
  82. data/spec/shared_contexts/l10n.rb +5 -0
  83. data/spec/unit/agent_spec.rb +28 -2
  84. data/spec/unit/application/agent_spec.rb +26 -16
  85. data/spec/unit/application/lookup_spec.rb +131 -10
  86. data/spec/unit/concurrent/thread_local_singleton_spec.rb +39 -0
  87. data/spec/unit/configurer_spec.rb +124 -61
  88. data/spec/unit/daemon_spec.rb +2 -11
  89. data/spec/unit/face/generate_spec.rb +64 -0
  90. data/spec/unit/file_system_spec.rb +34 -4
  91. data/spec/unit/forge/module_release_spec.rb +3 -3
  92. data/spec/unit/functions/versioncmp_spec.rb +40 -4
  93. data/spec/unit/http/client_spec.rb +18 -0
  94. data/spec/unit/node_spec.rb +6 -0
  95. data/spec/unit/pops/parser/parse_containers_spec.rb +2 -2
  96. data/spec/unit/pops/serialization/to_from_hr_spec.rb +0 -58
  97. data/spec/unit/pops/validator/validator_spec.rb +5 -0
  98. data/spec/unit/provider/package/puppetserver_gem_spec.rb +2 -2
  99. data/spec/unit/provider/package/windows/exe_package_spec.rb +17 -0
  100. data/spec/unit/provider/service/gentoo_spec.rb +6 -5
  101. data/spec/unit/provider/service/init_spec.rb +15 -9
  102. data/spec/unit/provider/service/openwrt_spec.rb +21 -29
  103. data/spec/unit/provider/service/redhat_spec.rb +3 -2
  104. data/spec/unit/ssl/ssl_provider_spec.rb +75 -1
  105. data/spec/unit/ssl/state_machine_spec.rb +1 -0
  106. data/spec/unit/transaction/persistence_spec.rb +51 -0
  107. data/spec/unit/type/user_spec.rb +0 -45
  108. data/spec/unit/util/json_spec.rb +126 -0
  109. data/spec/unit/util/windows_spec.rb +23 -0
  110. data/spec/unit/util/yaml_spec.rb +54 -29
  111. data/tasks/generate_cert_fixtures.rake +5 -4
  112. metadata +9 -3
@@ -66,7 +66,6 @@ module Puppet
66
66
  newproperty(:ensure, :parent => Puppet::Property::Ensure) do
67
67
  newvalue(:present, :event => :user_created) do
68
68
  provider.create
69
- @resource.generate
70
69
  end
71
70
 
72
71
  newvalue(:absent, :event => :user_removed) do
@@ -228,6 +227,9 @@ module Puppet
228
227
  * OS X 10.8 and higher use salted SHA512 PBKDF2 hashes. When managing passwords
229
228
  on these systems, the `salt` and `iterations` attributes need to be specified as
230
229
  well as the password.
230
+ * macOS 10.15 and higher require the salt to be 32-bytes. Since Puppet's user
231
+ resource requires the value to be hex encoded, the length of the salt's
232
+ string must be 64.
231
233
  * Windows passwords can be managed only in cleartext, because there is no Windows
232
234
  API for setting the password hash.
233
235
 
@@ -695,7 +697,6 @@ module Puppet
695
697
 
696
698
  def generate
697
699
  if !self[:purge_ssh_keys].empty?
698
- return [] if self[:ensure] == :present && !provider.exists?
699
700
  if Puppet::Type.type(:ssh_authorized_key).nil?
700
701
  warning _("Ssh_authorized_key type is not available. Cannot purge SSH keys.")
701
702
  else
@@ -744,6 +745,45 @@ module Puppet
744
745
  end
745
746
  raise ArgumentError, _("purge_ssh_keys must be true, false, or an array of file names, not %{value}") % { value: value.inspect }
746
747
  end
748
+
749
+ munge do |value|
750
+ # Resolve string, boolean and symbol forms of true and false to a
751
+ # single representation.
752
+ case value
753
+ when :false, false, "false"
754
+ []
755
+ when :true, true, "true"
756
+ home = homedir
757
+ home ? [ "#{home}/.ssh/authorized_keys" ] : []
758
+ else
759
+ # value can be a string or array - munge each value
760
+ [ value ].flatten.map do |entry|
761
+ authorized_keys_path(entry)
762
+ end.compact
763
+ end
764
+ end
765
+
766
+ private
767
+
768
+ def homedir
769
+ resource[:home] || Dir.home(resource[:name])
770
+ rescue ArgumentError
771
+ Puppet.debug("User '#{resource[:name]}' does not exist")
772
+ nil
773
+ end
774
+
775
+ def authorized_keys_path(entry)
776
+ return entry unless entry.match?(%r{^(?:~|%h)/})
777
+
778
+ # if user doesn't exist (yet), ignore nonexistent homedir
779
+ home = homedir
780
+ return nil unless home
781
+
782
+ # compiler freezes "value" so duplicate using a gsub, second mutating gsub! is then ok
783
+ entry = entry.gsub(%r{^~/}, "#{home}/")
784
+ entry.gsub!(%r{^%h/}, "#{home}/")
785
+ entry
786
+ end
747
787
  end
748
788
 
749
789
  newproperty(:loginclass, :required_features => :manages_loginclass) do
@@ -765,7 +805,7 @@ module Puppet
765
805
  # @see generate
766
806
  # @api private
767
807
  def find_unmanaged_keys
768
- munged_unmanaged_keys.
808
+ self[:purge_ssh_keys].
769
809
  select { |f| File.readable?(f) }.
770
810
  map { |f| unknown_keys_in_file(f) }.
771
811
  flatten.each do |res|
@@ -777,41 +817,6 @@ module Puppet
777
817
  end
778
818
  end
779
819
 
780
- def munged_unmanaged_keys
781
- value = self[:purge_ssh_keys]
782
-
783
- # Resolve string, boolean and symbol forms of true and false to a
784
- # single representation.
785
- test_sym = value.to_s.intern
786
- value = test_sym if [:true, :false].include? test_sym
787
-
788
- return [] if value == :false
789
-
790
- home = self[:home]
791
- begin
792
- home ||= provider.home
793
- rescue
794
- Puppet.debug("User '#{self[:name]}' does not exist")
795
- end
796
-
797
- if home.to_s.empty? || !Dir.exist?(home.to_s)
798
- if value == :true || [ value ].flatten.any? { |v| v.start_with?('~/', '%h/') }
799
- Puppet.debug("User '#{self[:name]}' has no home directory set to purge ssh keys from.")
800
- return []
801
- end
802
- end
803
-
804
- return [ "#{home}/.ssh/authorized_keys" ] if value == :true
805
-
806
- # value is an array - munge each value
807
- [ value ].flatten.map do |entry|
808
- # make sure frozen value is duplicated by using a gsub, second mutating gsub! is then ok
809
- entry = entry.gsub(/^~\//, "#{home}/")
810
- entry.gsub!(/^%h\//, "#{home}/")
811
- entry
812
- end
813
- end
814
-
815
820
  # Parse an ssh authorized keys file superficially, extract the comments
816
821
  # on the keys. These are considered names of possible ssh_authorized_keys
817
822
  # resources. Keys that are managed by the present catalog are ignored.
@@ -26,6 +26,23 @@ module Puppet::Util
26
26
  require 'json'
27
27
  end
28
28
 
29
+ # Load the content from a file as JSON if
30
+ # contents are in valid format. This method does not
31
+ # raise error but returns `nil` when invalid file is
32
+ # given.
33
+ def self.load_file_if_valid(filename, options = {})
34
+ load_file(filename, options)
35
+ rescue Puppet::Util::Json::ParseError, ArgumentError, Errno::ENOENT => detail
36
+ Puppet.debug("Could not retrieve JSON content from '#{filename}': #{detail.message}")
37
+ nil
38
+ end
39
+
40
+ # Load the content from a file as JSON.
41
+ def self.load_file(filename, options = {})
42
+ json = Puppet::FileSystem.read(filename, :encoding => 'utf-8')
43
+ load(json, options)
44
+ end
45
+
29
46
  # These methods do similar processing to the fallback implemented by MultiJson
30
47
  # when using the built-in JSON backend, to ensure consistent behavior
31
48
  # whether or not MultiJson can be loaded.
@@ -105,9 +105,14 @@ class Puppet::Util::Log
105
105
  def Log.level=(level)
106
106
  level = level.intern unless level.is_a?(Symbol)
107
107
 
108
- raise Puppet::DevError, _("Invalid loglevel %{level}") % { level: level } unless @levels.include?(level)
108
+ # loglevel is a 0-based index
109
+ loglevel = @levels.index(level)
110
+ raise Puppet::DevError, _("Invalid loglevel %{level}") % { level: level } unless loglevel
109
111
 
110
- @loglevel = @levels.index(level)
112
+ return if @loglevel == loglevel
113
+
114
+ # loglevel changed
115
+ @loglevel = loglevel
111
116
 
112
117
  # Enable or disable Facter debugging
113
118
  Puppet.runtime[:facter].debugging(level == :debug)
@@ -39,6 +39,12 @@ unless Puppet::Util::Platform.jruby_fips?
39
39
  end
40
40
  end
41
41
 
42
+ unless defined?(OpenSSL::X509::V_ERR_HOSTNAME_MISMATCH)
43
+ module OpenSSL::X509
44
+ OpenSSL::X509::V_ERR_HOSTNAME_MISMATCH = 0x3E
45
+ end
46
+ end
47
+
42
48
  class OpenSSL::SSL::SSLContext
43
49
  if DEFAULT_PARAMS[:options]
44
50
  DEFAULT_PARAMS[:options] |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3
@@ -64,8 +70,6 @@ unless Puppet::Util::Platform.jruby_fips?
64
70
  end
65
71
 
66
72
  if Puppet::Util::Platform.windows?
67
- require 'puppet/util/windows'
68
-
69
73
  class OpenSSL::X509::Store
70
74
  @puppet_certs_loaded = false
71
75
  alias __original_set_default_paths set_default_paths
@@ -1,6 +1,13 @@
1
+ # frozen_string_literal: true
1
2
  module Puppet::Util::Package
2
- def versioncmp(version_a, version_b)
3
+ def versioncmp(version_a, version_b, ignore_trailing_zeroes = false)
3
4
  vre = /[-.]|\d+|[^-.\d]+/
5
+
6
+ if ignore_trailing_zeroes
7
+ version_a = normalize(version_a)
8
+ version_b = normalize(version_b)
9
+ end
10
+
4
11
  ax = version_a.scan(vre)
5
12
  bx = version_b.scan(vre)
6
13
 
@@ -8,24 +15,26 @@ module Puppet::Util::Package
8
15
  a = ax.shift
9
16
  b = bx.shift
10
17
 
11
- if( a == b ) then next
12
- elsif (a == '-' && b == '-') then next
13
- elsif (a == '-') then return -1
14
- elsif (b == '-') then return 1
15
- elsif (a == '.' && b == '.') then next
16
- elsif (a == '.' ) then return -1
17
- elsif (b == '.' ) then return 1
18
- elsif (a =~ /^\d+$/ && b =~ /^\d+$/) then
19
- if( a =~ /^0/ or b =~ /^0/ ) then
20
- return a.to_s.upcase <=> b.to_s.upcase
21
- end
18
+ next if a == b
19
+ return -1 if a == '-'
20
+ return 1 if b == '-'
21
+ return -1 if a == '.'
22
+ return 1 if b == '.'
23
+ if a =~ /^\d+$/ && b =~ /^\d+$/
24
+ return a.to_s.upcase <=> b.to_s.upcase if a =~ /^0/ || b =~ /^0/
22
25
  return a.to_i <=> b.to_i
23
- else
24
- return a.upcase <=> b.upcase
25
26
  end
27
+ return a.upcase <=> b.upcase
26
28
  end
27
- version_a <=> version_b;
29
+ version_a <=> version_b
28
30
  end
29
-
30
31
  module_function :versioncmp
32
+
33
+ def self.normalize(version)
34
+ version = version.split('-')
35
+ version.first.sub!(/([\.0]+)$/, '')
36
+
37
+ version.join('-')
38
+ end
39
+ private_class_method :normalize
31
40
  end
@@ -24,7 +24,11 @@ module Puppet::Util::Yaml
24
24
  # @raise [YamlLoadException] If deserialization fails.
25
25
  # @return The parsed YAML, which can be Hash, Array or scalar types.
26
26
  def self.safe_load(yaml, allowed_classes = [], filename = nil)
27
- data = YAML.safe_load(yaml, allowed_classes, [], true, filename)
27
+ if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0')
28
+ data = YAML.safe_load(yaml, permitted_classes: allowed_classes, aliases: true, filename: filename)
29
+ else
30
+ data = YAML.safe_load(yaml, allowed_classes, [], true, filename)
31
+ end
28
32
  data = false if data.nil?
29
33
  data
30
34
  rescue ::Psych::DisallowedClass => detail
@@ -42,6 +46,17 @@ module Puppet::Util::Yaml
42
46
  safe_load(yaml, allowed_classes, filename)
43
47
  end
44
48
 
49
+ # Safely load the content from a file as YAML if
50
+ # contents are in valid format. This method does not
51
+ # raise error but returns `nil` when invalid file is
52
+ # given.
53
+ def self.safe_load_file_if_valid(filename, allowed_classes = [])
54
+ safe_load_file(filename, allowed_classes)
55
+ rescue YamlLoadError, ArgumentError, Errno::ENOENT => detail
56
+ Puppet.debug("Could not retrieve YAML content from '#{filename}': #{detail.message}")
57
+ nil
58
+ end
59
+
45
60
  # @deprecated Use {#safe_load_file} instead.
46
61
  def self.load_file(filename, default_value = false, strip_classes = false)
47
62
  Puppet.deprecation_warning(_("Puppet::Util::Yaml.load_file is deprecated. Use safe_load_file instead."))
@@ -57,7 +72,11 @@ module Puppet::Util::Yaml
57
72
  end
58
73
  data.to_ruby || default_value
59
74
  else
60
- yaml = YAML.load_file(filename)
75
+ if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.3.2')
76
+ yaml = YAML.unsafe_load_file(filename)
77
+ else
78
+ yaml = YAML.load_file(filename)
79
+ end
61
80
  yaml || default_value
62
81
  end
63
82
  rescue *YamlLoadExceptions => detail
data/lib/puppet/util.rb CHANGED
@@ -7,6 +7,7 @@ require 'uri'
7
7
  require 'pathname'
8
8
  require 'ostruct'
9
9
  require 'puppet/util/platform'
10
+ require 'puppet/util/windows'
10
11
  require 'puppet/util/symbolic_file_mode'
11
12
  require 'puppet/file_system/uniquefile'
12
13
  require 'securerandom'
@@ -22,8 +23,6 @@ module Util
22
23
  require 'puppet/util/posix'
23
24
  extend Puppet::Util::POSIX
24
25
 
25
- require 'puppet/util/windows/process' if Puppet::Util::Platform.windows?
26
-
27
26
  extend Puppet::Util::SymbolicFileMode
28
27
 
29
28
  def default_env
@@ -6,7 +6,7 @@
6
6
  # Raketasks and such to set the version based on the output of `git describe`
7
7
 
8
8
  module Puppet
9
- PUPPETVERSION = '6.25.1'
9
+ PUPPETVERSION = '6.28.0'
10
10
 
11
11
  ##
12
12
  # version is a public API method intended to always provide a fast and
data/lib/puppet.rb CHANGED
@@ -242,20 +242,7 @@ module Puppet
242
242
  {
243
243
  :environments => Puppet::Environments::Cached.new(Puppet::Environments::Combined.new(*loaders)),
244
244
  :http_pool => proc { Puppet.runtime[:http].pool },
245
- :ssl_context => proc {
246
- begin
247
- cert = Puppet::X509::CertProvider.new
248
- password = cert.load_private_key_password
249
- ssl = Puppet::SSL::SSLProvider.new
250
- ssl.load_context(certname: Puppet[:certname], password: password)
251
- rescue => e
252
- # TRANSLATORS: `message` is an already translated string of why SSL failed to initialize
253
- Puppet.log_exception(e, _("Failed to initialize SSL: %{message}") % { message: e.message })
254
- # TRANSLATORS: `puppet agent -t` is a command and should not be translated
255
- Puppet.err(_("Run `puppet agent -t`"))
256
- raise e
257
- end
258
- },
245
+ :ssl_context => proc { Puppet.runtime[:http].default_ssl_context },
259
246
  :ssl_host => proc { Puppet::SSL::Host.localhost(true) },
260
247
  :http_session => proc { Puppet.runtime[:http].create_session },
261
248
  :plugins => proc { Puppet::Plugins::Configuration.load_plugins },
@@ -364,3 +351,4 @@ require 'puppet/status'
364
351
  require 'puppet/file_bucket/file'
365
352
  require 'puppet/plugins/configuration'
366
353
  require 'puppet/pal/pal_api'
354
+ require 'puppet/node/facts'