puppet 6.25.0-x86-mingw32 → 6.27.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.
- checksums.yaml +4 -4
- data/CODEOWNERS +1 -1
- data/Gemfile +2 -2
- data/Gemfile.lock +39 -32
- data/lib/puppet/application/lookup.rb +74 -24
- data/lib/puppet/concurrent/thread_local_singleton.rb +5 -3
- data/lib/puppet/configurer.rb +65 -11
- data/lib/puppet/defaults.rb +19 -3
- data/lib/puppet/face/generate.rb +2 -0
- data/lib/puppet/file_serving/metadata.rb +3 -0
- data/lib/puppet/file_system/file_impl.rb +7 -7
- data/lib/puppet/file_system/jruby.rb +1 -1
- data/lib/puppet/file_system/windows.rb +4 -4
- data/lib/puppet/file_system.rb +1 -1
- data/lib/puppet/functions/next.rb +18 -1
- data/lib/puppet/functions/tree_each.rb +0 -1
- data/lib/puppet/functions/versioncmp.rb +6 -2
- data/lib/puppet/generate/type.rb +9 -0
- data/lib/puppet/http/client.rb +1 -1
- data/lib/puppet/http/redirector.rb +5 -0
- data/lib/puppet/node.rb +1 -1
- data/lib/puppet/parser/resource.rb +1 -1
- data/lib/puppet/pops/evaluator/closure.rb +7 -5
- data/lib/puppet/pops/evaluator/runtime3_resource_support.rb +1 -0
- data/lib/puppet/pops/parser/code_merger.rb +4 -4
- data/lib/puppet/pops/parser/egrammar.ra +2 -0
- data/lib/puppet/pops/parser/eparser.rb +813 -794
- data/lib/puppet/pops/serialization/to_data_converter.rb +6 -18
- data/lib/puppet/provider/service/init.rb +5 -4
- data/lib/puppet/resource/catalog.rb +1 -1
- data/lib/puppet/resource.rb +38 -5
- data/lib/puppet/ssl/ssl_provider.rb +10 -7
- data/lib/puppet/ssl/verifier.rb +6 -0
- data/lib/puppet/transaction/persistence.rb +22 -12
- data/lib/puppet/type/exec.rb +1 -1
- data/lib/puppet/type/file/data_sync.rb +1 -1
- data/lib/puppet/type/user.rb +40 -38
- data/lib/puppet/util/json.rb +17 -0
- data/lib/puppet/util/log.rb +7 -2
- data/lib/puppet/util/monkey_patches.rb +6 -2
- data/lib/puppet/util/package.rb +25 -16
- data/lib/puppet/util/windows/service.rb +0 -5
- data/lib/puppet/util/windows.rb +3 -0
- data/lib/puppet/util/yaml.rb +21 -2
- data/lib/puppet/util.rb +1 -2
- data/lib/puppet/version.rb +1 -1
- data/lib/puppet.rb +1 -0
- data/locales/puppet.pot +5 -10454
- data/man/man5/puppet.conf.5 +21 -2
- data/man/man8/puppet-agent.8 +1 -1
- data/man/man8/puppet-apply.8 +1 -1
- data/man/man8/puppet-catalog.8 +1 -1
- data/man/man8/puppet-config.8 +1 -1
- data/man/man8/puppet-describe.8 +1 -1
- data/man/man8/puppet-device.8 +1 -1
- data/man/man8/puppet-doc.8 +1 -1
- data/man/man8/puppet-epp.8 +1 -1
- data/man/man8/puppet-facts.8 +1 -1
- data/man/man8/puppet-filebucket.8 +1 -1
- data/man/man8/puppet-generate.8 +1 -1
- data/man/man8/puppet-help.8 +1 -1
- data/man/man8/puppet-key.8 +1 -1
- data/man/man8/puppet-lookup.8 +9 -6
- data/man/man8/puppet-man.8 +1 -1
- data/man/man8/puppet-module.8 +1 -1
- data/man/man8/puppet-node.8 +1 -1
- data/man/man8/puppet-parser.8 +1 -1
- data/man/man8/puppet-plugin.8 +1 -1
- data/man/man8/puppet-report.8 +1 -1
- data/man/man8/puppet-resource.8 +1 -1
- data/man/man8/puppet-script.8 +1 -1
- data/man/man8/puppet-ssl.8 +1 -1
- data/man/man8/puppet-status.8 +1 -1
- data/man/man8/puppet.8 +2 -2
- data/spec/fixtures/integration/application/agent/cached_deferred_catalog.json +2 -1
- data/spec/fixtures/unit/forge/bacula.json +1 -1
- data/spec/integration/application/agent_spec.rb +28 -0
- data/spec/integration/application/lookup_spec.rb +81 -50
- data/spec/integration/application/resource_spec.rb +6 -2
- data/spec/integration/http/client_spec.rb +30 -0
- data/spec/integration/parser/pcore_resource_spec.rb +10 -0
- data/spec/shared_contexts/l10n.rb +5 -0
- data/spec/unit/application/lookup_spec.rb +131 -10
- data/spec/unit/concurrent/thread_local_singleton_spec.rb +39 -0
- data/spec/unit/configurer_spec.rb +197 -73
- data/spec/unit/face/generate_spec.rb +64 -0
- data/spec/unit/file_system_spec.rb +34 -4
- data/spec/unit/forge/module_release_spec.rb +3 -3
- data/spec/unit/functions/versioncmp_spec.rb +40 -4
- data/spec/unit/http/client_spec.rb +58 -1
- data/spec/unit/node_spec.rb +6 -0
- data/spec/unit/pops/parser/parse_containers_spec.rb +2 -2
- data/spec/unit/pops/serialization/to_from_hr_spec.rb +0 -58
- data/spec/unit/pops/validator/validator_spec.rb +5 -0
- data/spec/unit/provider/service/gentoo_spec.rb +6 -5
- data/spec/unit/provider/service/init_spec.rb +15 -9
- data/spec/unit/provider/service/openwrt_spec.rb +21 -29
- data/spec/unit/provider/service/redhat_spec.rb +3 -2
- data/spec/unit/resource/catalog_spec.rb +14 -1
- data/spec/unit/resource_spec.rb +58 -2
- data/spec/unit/transaction/persistence_spec.rb +51 -0
- data/spec/unit/type/user_spec.rb +0 -45
- data/spec/unit/util/json_spec.rb +126 -0
- data/spec/unit/util/windows_spec.rb +23 -0
- data/spec/unit/util/yaml_spec.rb +54 -29
- metadata +9 -3
@@ -14,8 +14,6 @@ module Serialization
|
|
14
14
|
# @option options [Boolean] :local_reference use local references instead of duplicating complex entries
|
15
15
|
# @option options [Boolean] :type_by_reference `true` if Object types are converted to references rather than embedded.
|
16
16
|
# @option options [Boolean] :symbol_as_string `true` if Symbols should be converted to strings (with type loss)
|
17
|
-
# @option options [Boolean] :force_symbol `false` if Symbols should not be converted (rich_data and symbol_as_string must be false)
|
18
|
-
# @option options [Boolean] :silence_warnings `false` if warnings should be silenced
|
19
17
|
# @option options [String] :message_prefix String to prepend to in warnings and errors
|
20
18
|
# @return [Data] the processed result. An object assignable to `Data`.
|
21
19
|
#
|
@@ -43,12 +41,6 @@ module Serialization
|
|
43
41
|
@symbol_as_string = options[:symbol_as_string]
|
44
42
|
@symbol_as_string = false if @symbol_as_string.nil?
|
45
43
|
|
46
|
-
@force_symbol = options[:force_symbol]
|
47
|
-
@force_symbol = false if @force_symbol.nil?
|
48
|
-
|
49
|
-
@silence_warnings = options[:silence_warnings]
|
50
|
-
@silence_warnings = false if @silence_warnings.nil?
|
51
|
-
|
52
44
|
@rich_data = options[:rich_data]
|
53
45
|
@rich_data = false if @rich_data.nil?
|
54
46
|
|
@@ -100,11 +92,7 @@ module Serialization
|
|
100
92
|
elsif @rich_data
|
101
93
|
{ PCORE_TYPE_KEY => PCORE_TYPE_SYMBOL, PCORE_VALUE_KEY => value.to_s }
|
102
94
|
else
|
103
|
-
|
104
|
-
value
|
105
|
-
else
|
106
|
-
@silence_warnings ? unknown_to_string(value) : unknown_to_string_with_warning(value)
|
107
|
-
end
|
95
|
+
unknown_to_string_with_warning(value)
|
108
96
|
end
|
109
97
|
elsif value.instance_of?(Array)
|
110
98
|
process(value) do
|
@@ -129,11 +117,7 @@ module Serialization
|
|
129
117
|
{ PCORE_TYPE_KEY => PCORE_TYPE_SENSITIVE, PCORE_VALUE_KEY => to_data(value.unwrap) }
|
130
118
|
end
|
131
119
|
else
|
132
|
-
|
133
|
-
value_to_data_hash(value)
|
134
|
-
else
|
135
|
-
@silence_warnings ? unknown_to_string(value) : unknown_to_string_with_warning(value)
|
136
|
-
end
|
120
|
+
unknown_to_data(value)
|
137
121
|
end
|
138
122
|
end
|
139
123
|
|
@@ -207,6 +191,10 @@ module Serialization
|
|
207
191
|
v
|
208
192
|
end
|
209
193
|
|
194
|
+
def unknown_to_data(value)
|
195
|
+
@rich_data ? value_to_data_hash(value) : unknown_to_string_with_warning(value)
|
196
|
+
end
|
197
|
+
|
210
198
|
def unknown_key_to_string_with_warning(value)
|
211
199
|
str = unknown_to_string(value)
|
212
200
|
serialization_issue(Issues::SERIALIZATION_UNKNOWN_KEY_CONVERTED_TO_STRING, :path => path_to_s, :klass => value.class, :value => str)
|
@@ -84,7 +84,7 @@ Puppet::Type.type(:service).provide :init, :parent => :base do
|
|
84
84
|
defpath = [defpath] unless defpath.is_a? Array
|
85
85
|
instances = []
|
86
86
|
defpath.each do |path|
|
87
|
-
unless
|
87
|
+
unless Puppet::FileSystem.directory?(path)
|
88
88
|
Puppet.debug "Service path #{path} does not exist"
|
89
89
|
next
|
90
90
|
end
|
@@ -97,8 +97,9 @@ Puppet::Type.type(:service).provide :init, :parent => :base do
|
|
97
97
|
fullpath = File.join(path, name)
|
98
98
|
next if name =~ /^\./
|
99
99
|
next if exclude.include? name
|
100
|
-
next if
|
101
|
-
next
|
100
|
+
next if Puppet::FileSystem.directory?(fullpath)
|
101
|
+
next unless Puppet::FileSystem.executable?(fullpath)
|
102
|
+
next unless is_init?(fullpath)
|
102
103
|
instances << new(:name => name, :path => path, :hasstatus => true)
|
103
104
|
end
|
104
105
|
end
|
@@ -122,7 +123,7 @@ Puppet::Type.type(:service).provide :init, :parent => :base do
|
|
122
123
|
|
123
124
|
def paths
|
124
125
|
@paths ||= @resource[:path].find_all do |path|
|
125
|
-
if
|
126
|
+
if Puppet::FileSystem.directory?(path)
|
126
127
|
true
|
127
128
|
else
|
128
129
|
if Puppet::FileSystem.exist?(path)
|
data/lib/puppet/resource.rb
CHANGED
@@ -11,7 +11,7 @@ class Puppet::Resource
|
|
11
11
|
include Puppet::Util::PsychSupport
|
12
12
|
|
13
13
|
include Enumerable
|
14
|
-
attr_accessor :file, :line, :catalog, :exported, :virtual, :strict
|
14
|
+
attr_accessor :file, :line, :catalog, :exported, :virtual, :strict, :kind
|
15
15
|
attr_reader :type, :title, :parameters
|
16
16
|
|
17
17
|
# @!attribute [rw] sensitive_parameters
|
@@ -29,11 +29,16 @@ class Puppet::Resource
|
|
29
29
|
EMPTY_ARRAY = [].freeze
|
30
30
|
EMPTY_HASH = {}.freeze
|
31
31
|
|
32
|
-
ATTRIBUTES = [:file, :line, :exported].freeze
|
32
|
+
ATTRIBUTES = [:file, :line, :exported, :kind].freeze
|
33
33
|
TYPE_CLASS = 'Class'.freeze
|
34
34
|
TYPE_NODE = 'Node'.freeze
|
35
35
|
TYPE_SITE = 'Site'.freeze
|
36
36
|
|
37
|
+
CLASS_STRING = 'class'.freeze
|
38
|
+
DEFINED_TYPE_STRING = 'defined_type'.freeze
|
39
|
+
COMPILABLE_TYPE_STRING = 'compilable_type'.freeze
|
40
|
+
UNKNOWN_TYPE_STRING = 'unknown'.freeze
|
41
|
+
|
37
42
|
PCORE_TYPE_KEY = '__ptype'.freeze
|
38
43
|
VALUE_KEY = 'value'.freeze
|
39
44
|
|
@@ -194,6 +199,18 @@ class Puppet::Resource
|
|
194
199
|
resource_type.is_a?(Puppet::CompilableResourceType)
|
195
200
|
end
|
196
201
|
|
202
|
+
def self.to_kind(resource_type)
|
203
|
+
if resource_type == CLASS_STRING
|
204
|
+
CLASS_STRING
|
205
|
+
elsif resource_type.is_a?(Puppet::Resource::Type) && resource_type.type == :definition
|
206
|
+
DEFINED_TYPE_STRING
|
207
|
+
elsif resource_type.is_a?(Puppet::CompilableResourceType)
|
208
|
+
COMPILABLE_TYPE_STRING
|
209
|
+
else
|
210
|
+
UNKNOWN_TYPE_STRING
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
197
214
|
# Iterate over each param/value pair, as required for Enumerable.
|
198
215
|
def each
|
199
216
|
parameters.each { |p,v| yield p, v }
|
@@ -248,6 +265,7 @@ class Puppet::Resource
|
|
248
265
|
src = type
|
249
266
|
self.file = src.file
|
250
267
|
self.line = src.line
|
268
|
+
self.kind = src.kind
|
251
269
|
self.exported = src.exported
|
252
270
|
self.virtual = src.virtual
|
253
271
|
self.set_tags(src)
|
@@ -310,6 +328,7 @@ class Puppet::Resource
|
|
310
328
|
|
311
329
|
rt = resource_type
|
312
330
|
|
331
|
+
self.kind = self.class.to_kind(rt) unless kind
|
313
332
|
if strict? && rt.nil?
|
314
333
|
if self.class?
|
315
334
|
raise ArgumentError, _("Could not find declared class %{title}") % { title: title }
|
@@ -493,10 +512,24 @@ class Puppet::Resource
|
|
493
512
|
ref
|
494
513
|
end
|
495
514
|
|
496
|
-
# Convert our resource to a RAL resource instance.
|
497
|
-
# instances for resource types that
|
515
|
+
# Convert our resource to a RAL resource instance. Creates component
|
516
|
+
# instances for resource types that are not of a compilable_type kind. In case
|
517
|
+
# the resource doesn’t exist and it’s compilable_type kind, raise an error.
|
518
|
+
# There are certain cases where a resource won't be in a catalog, such as
|
519
|
+
# when we create a resource directly by using Puppet::Resource.new(...), so we
|
520
|
+
# must check its kind before deciding whether the catalog format is of an older
|
521
|
+
# version or not.
|
498
522
|
def to_ral
|
499
|
-
|
523
|
+
if self.kind == COMPILABLE_TYPE_STRING
|
524
|
+
typeklass = Puppet::Type.type(self.type)
|
525
|
+
elsif self.catalog && self.catalog.catalog_format >= 2
|
526
|
+
typeklass = Puppet::Type.type(:component)
|
527
|
+
else
|
528
|
+
typeklass = Puppet::Type.type(self.type) || Puppet::Type.type(:component)
|
529
|
+
end
|
530
|
+
|
531
|
+
raise(Puppet::Error, "Resource type '#{self.type}' was not found") unless typeklass
|
532
|
+
|
500
533
|
typeklass.new(self)
|
501
534
|
end
|
502
535
|
|
@@ -51,8 +51,7 @@ class Puppet::SSL::SSLProvider
|
|
51
51
|
# @raise (see #create_context)
|
52
52
|
# @api private
|
53
53
|
def create_system_context(cacerts:, path: Puppet[:ssl_trust_store])
|
54
|
-
store = create_x509_store(cacerts, [], false)
|
55
|
-
store.set_default_paths
|
54
|
+
store = create_x509_store(cacerts, [], false, include_system_store: true)
|
56
55
|
|
57
56
|
if path
|
58
57
|
stat = Puppet::FileSystem.stat(path)
|
@@ -94,19 +93,20 @@ class Puppet::SSL::SSLProvider
|
|
94
93
|
# @param client_cert [OpenSSL::X509::Certificate] client's cert whose public
|
95
94
|
# key matches the `private_key`
|
96
95
|
# @param revocation [:chain, :leaf, false] revocation mode
|
96
|
+
# @param include_system_store [true, false] Also trust system CA
|
97
97
|
# @return [Puppet::SSL::SSLContext] A context to use to create connections
|
98
98
|
# @raise [Puppet::SSL::CertVerifyError] There was an issue with
|
99
99
|
# one of the certs or CRLs.
|
100
100
|
# @raise [Puppet::SSL::SSLError] There was an issue with the
|
101
101
|
# `private_key`.
|
102
102
|
# @api private
|
103
|
-
def create_context(cacerts:, crls:, private_key:, client_cert:, revocation: Puppet[:certificate_revocation])
|
103
|
+
def create_context(cacerts:, crls:, private_key:, client_cert:, revocation: Puppet[:certificate_revocation], include_system_store: false)
|
104
104
|
raise ArgumentError, _("CA certs are missing") unless cacerts
|
105
105
|
raise ArgumentError, _("CRLs are missing") unless crls
|
106
106
|
raise ArgumentError, _("Private key is missing") unless private_key
|
107
107
|
raise ArgumentError, _("Client cert is missing") unless client_cert
|
108
108
|
|
109
|
-
store = create_x509_store(cacerts, crls, revocation)
|
109
|
+
store = create_x509_store(cacerts, crls, revocation, include_system_store: include_system_store)
|
110
110
|
client_chain = verify_cert_with_store(store, client_cert)
|
111
111
|
|
112
112
|
if !private_key.is_a?(OpenSSL::PKey::RSA) && !private_key.is_a?(OpenSSL::PKey::EC)
|
@@ -134,12 +134,13 @@ class Puppet::SSL::SSLProvider
|
|
134
134
|
# @param password [String, nil] If the private key is encrypted, decrypt
|
135
135
|
# it using the password. If the key is encrypted, but a password is
|
136
136
|
# not specified, then the key cannot be loaded.
|
137
|
+
# @param include_system_store [true, false] Also trust system CA
|
137
138
|
# @return [Puppet::SSL::SSLContext] A context to use to create connections
|
138
139
|
# @raise [Puppet::SSL::CertVerifyError] There was an issue with
|
139
140
|
# one of the certs or CRLs.
|
140
141
|
# @raise [Puppet::Error] There was an issue with one of the required components.
|
141
142
|
# @api private
|
142
|
-
def load_context(certname: Puppet[:certname], revocation: Puppet[:certificate_revocation], password: nil)
|
143
|
+
def load_context(certname: Puppet[:certname], revocation: Puppet[:certificate_revocation], password: nil, include_system_store: false)
|
143
144
|
cert = Puppet::X509::CertProvider.new
|
144
145
|
cacerts = cert.load_cacerts(required: true)
|
145
146
|
crls = case revocation
|
@@ -151,7 +152,7 @@ class Puppet::SSL::SSLProvider
|
|
151
152
|
private_key = cert.load_private_key(certname, required: true, password: password)
|
152
153
|
client_cert = cert.load_client_cert(certname, required: true)
|
153
154
|
|
154
|
-
create_context(cacerts: cacerts, crls: crls, private_key: private_key, client_cert: client_cert, revocation: revocation)
|
155
|
+
create_context(cacerts: cacerts, crls: crls, private_key: private_key, client_cert: client_cert, revocation: revocation, include_system_store: include_system_store)
|
155
156
|
rescue OpenSSL::PKey::PKeyError => e
|
156
157
|
raise Puppet::SSL::SSLError.new(_("Failed to load private key for host '%{name}': %{message}") % { name: certname, message: e.message }, e)
|
157
158
|
end
|
@@ -186,7 +187,7 @@ class Puppet::SSL::SSLProvider
|
|
186
187
|
end
|
187
188
|
end
|
188
189
|
|
189
|
-
def create_x509_store(roots, crls, revocation)
|
190
|
+
def create_x509_store(roots, crls, revocation, include_system_store: false)
|
190
191
|
store = OpenSSL::X509::Store.new
|
191
192
|
store.purpose = OpenSSL::X509::PURPOSE_ANY
|
192
193
|
store.flags = default_flags | revocation_mode(revocation)
|
@@ -194,6 +195,8 @@ class Puppet::SSL::SSLProvider
|
|
194
195
|
roots.each { |cert| store.add_cert(cert) }
|
195
196
|
crls.each { |crl| store.add_crl(crl) }
|
196
197
|
|
198
|
+
store.set_default_paths if include_system_store
|
199
|
+
|
197
200
|
store
|
198
201
|
end
|
199
202
|
|
data/lib/puppet/ssl/verifier.rb
CHANGED
@@ -115,6 +115,12 @@ class Puppet::SSL::Verifier
|
|
115
115
|
return false
|
116
116
|
end
|
117
117
|
|
118
|
+
# ruby-openssl#74ef8c0cc56b840b772240f2ee2b0fc0aafa2743 now sets the
|
119
|
+
# store_context error when the cert is mismatched
|
120
|
+
when OpenSSL::X509::V_ERR_HOSTNAME_MISMATCH
|
121
|
+
@last_error = Puppet::SSL::CertMismatchError.new(peer_cert, @hostname)
|
122
|
+
return false
|
123
|
+
|
118
124
|
when OpenSSL::X509::V_ERR_CRL_NOT_YET_VALID
|
119
125
|
crl = store_context.current_crl
|
120
126
|
if crl && crl.last_update && crl.last_update < Time.now + FIVE_MINUTES_AS_SECONDS
|
@@ -6,6 +6,26 @@ require 'puppet/util/yaml'
|
|
6
6
|
# as calculating corrective_change).
|
7
7
|
# @api private
|
8
8
|
class Puppet::Transaction::Persistence
|
9
|
+
|
10
|
+
def self.allowed_classes
|
11
|
+
@allowed_classes ||= [
|
12
|
+
Symbol,
|
13
|
+
Time,
|
14
|
+
Regexp,
|
15
|
+
# URI is excluded, because it serializes all instance variables including the
|
16
|
+
# URI parser. Better to serialize the URL encoded representation.
|
17
|
+
SemanticPuppet::Version,
|
18
|
+
# SemanticPuppet::VersionRange has many nested classes and is unlikely to be
|
19
|
+
# used directly, so ignore it
|
20
|
+
Puppet::Pops::Time::Timestamp,
|
21
|
+
Puppet::Pops::Time::TimeData,
|
22
|
+
Puppet::Pops::Time::Timespan,
|
23
|
+
Puppet::Pops::Types::PBinaryType::Binary,
|
24
|
+
# Puppet::Pops::Types::PSensitiveType::Sensitive values are excluded from
|
25
|
+
# the persistence store, ignore it.
|
26
|
+
].freeze
|
27
|
+
end
|
28
|
+
|
9
29
|
def initialize
|
10
30
|
@old_data = {}
|
11
31
|
@new_data = {"resources" => {}}
|
@@ -62,7 +82,7 @@ class Puppet::Transaction::Persistence
|
|
62
82
|
result = nil
|
63
83
|
Puppet::Util.benchmark(:debug, _("Loaded transaction store file in %{seconds} seconds")) do
|
64
84
|
begin
|
65
|
-
result = Puppet::Util::Yaml.safe_load_file(filename,
|
85
|
+
result = Puppet::Util::Yaml.safe_load_file(filename, self.class.allowed_classes)
|
66
86
|
rescue Puppet::Util::Yaml::YamlLoadError => detail
|
67
87
|
Puppet.log_exception(detail, _("Transaction store file %{filename} is corrupt (%{detail}); replacing") % { filename: filename, detail: detail })
|
68
88
|
|
@@ -87,17 +107,7 @@ class Puppet::Transaction::Persistence
|
|
87
107
|
|
88
108
|
# Save data from internal class to persistence store on disk.
|
89
109
|
def save
|
90
|
-
|
91
|
-
@new_data, {
|
92
|
-
symbol_as_string: false,
|
93
|
-
local_reference: false,
|
94
|
-
type_by_reference: true,
|
95
|
-
force_symbol: true,
|
96
|
-
silence_warnings: true,
|
97
|
-
message_prefix: to_s
|
98
|
-
}
|
99
|
-
)
|
100
|
-
Puppet::Util::Yaml.dump(converted_data, Puppet[:transactionstorefile])
|
110
|
+
Puppet::Util::Yaml.dump(@new_data, Puppet[:transactionstorefile])
|
101
111
|
end
|
102
112
|
|
103
113
|
# Use the catalog and run_mode to determine if persistence should be enabled or not
|
data/lib/puppet/type/exec.rb
CHANGED
@@ -457,7 +457,7 @@ module Puppet
|
|
457
457
|
|
458
458
|
exec { '/bin/echo root >> /usr/lib/cron/cron.allow':
|
459
459
|
path => '/usr/bin:/usr/sbin:/bin',
|
460
|
-
unless => 'grep root /usr/lib/cron/cron.allow 2>/dev/null',
|
460
|
+
unless => 'grep ^root$ /usr/lib/cron/cron.allow 2>/dev/null',
|
461
461
|
}
|
462
462
|
|
463
463
|
This would add `root` to the cron.allow file (on Solaris) unless
|
@@ -79,7 +79,7 @@ module Puppet
|
|
79
79
|
return :absent unless stat
|
80
80
|
ftype = stat.ftype
|
81
81
|
# Don't even try to manage the content on directories or links
|
82
|
-
return nil if [
|
82
|
+
return nil if ['directory', 'link', 'fifo', 'socket'].include?(ftype)
|
83
83
|
|
84
84
|
begin
|
85
85
|
resource.parameter(:checksum).sum_file(resource[:path])
|
data/lib/puppet/type/user.rb
CHANGED
@@ -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
|
@@ -695,7 +694,6 @@ module Puppet
|
|
695
694
|
|
696
695
|
def generate
|
697
696
|
if !self[:purge_ssh_keys].empty?
|
698
|
-
return [] if self[:ensure] == :present && !provider.exists?
|
699
697
|
if Puppet::Type.type(:ssh_authorized_key).nil?
|
700
698
|
warning _("Ssh_authorized_key type is not available. Cannot purge SSH keys.")
|
701
699
|
else
|
@@ -744,6 +742,45 @@ module Puppet
|
|
744
742
|
end
|
745
743
|
raise ArgumentError, _("purge_ssh_keys must be true, false, or an array of file names, not %{value}") % { value: value.inspect }
|
746
744
|
end
|
745
|
+
|
746
|
+
munge do |value|
|
747
|
+
# Resolve string, boolean and symbol forms of true and false to a
|
748
|
+
# single representation.
|
749
|
+
case value
|
750
|
+
when :false, false, "false"
|
751
|
+
[]
|
752
|
+
when :true, true, "true"
|
753
|
+
home = homedir
|
754
|
+
home ? [ "#{home}/.ssh/authorized_keys" ] : []
|
755
|
+
else
|
756
|
+
# value can be a string or array - munge each value
|
757
|
+
[ value ].flatten.map do |entry|
|
758
|
+
authorized_keys_path(entry)
|
759
|
+
end.compact
|
760
|
+
end
|
761
|
+
end
|
762
|
+
|
763
|
+
private
|
764
|
+
|
765
|
+
def homedir
|
766
|
+
resource[:home] || Dir.home(resource[:name])
|
767
|
+
rescue ArgumentError
|
768
|
+
Puppet.debug("User '#{resource[:name]}' does not exist")
|
769
|
+
nil
|
770
|
+
end
|
771
|
+
|
772
|
+
def authorized_keys_path(entry)
|
773
|
+
return entry unless entry.match?(%r{^(?:~|%h)/})
|
774
|
+
|
775
|
+
# if user doesn't exist (yet), ignore nonexistent homedir
|
776
|
+
home = homedir
|
777
|
+
return nil unless home
|
778
|
+
|
779
|
+
# compiler freezes "value" so duplicate using a gsub, second mutating gsub! is then ok
|
780
|
+
entry = entry.gsub(%r{^~/}, "#{home}/")
|
781
|
+
entry.gsub!(%r{^%h/}, "#{home}/")
|
782
|
+
entry
|
783
|
+
end
|
747
784
|
end
|
748
785
|
|
749
786
|
newproperty(:loginclass, :required_features => :manages_loginclass) do
|
@@ -765,7 +802,7 @@ module Puppet
|
|
765
802
|
# @see generate
|
766
803
|
# @api private
|
767
804
|
def find_unmanaged_keys
|
768
|
-
|
805
|
+
self[:purge_ssh_keys].
|
769
806
|
select { |f| File.readable?(f) }.
|
770
807
|
map { |f| unknown_keys_in_file(f) }.
|
771
808
|
flatten.each do |res|
|
@@ -777,41 +814,6 @@ module Puppet
|
|
777
814
|
end
|
778
815
|
end
|
779
816
|
|
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
817
|
# Parse an ssh authorized keys file superficially, extract the comments
|
816
818
|
# on the keys. These are considered names of possible ssh_authorized_keys
|
817
819
|
# resources. Keys that are managed by the present catalog are ignored.
|
data/lib/puppet/util/json.rb
CHANGED
@@ -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.
|
data/lib/puppet/util/log.rb
CHANGED
@@ -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
|
-
|
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
|
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
|
data/lib/puppet/util/package.rb
CHANGED
@@ -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
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
@@ -13,11 +13,6 @@ module Puppet::Util::Windows
|
|
13
13
|
|
14
14
|
FILE = Puppet::Util::Windows::File
|
15
15
|
|
16
|
-
# integer value of the floor for timeouts when waiting for service pending states.
|
17
|
-
# puppet will wait the length of dwWaitHint if it is longer than this value, but
|
18
|
-
# no shorter
|
19
|
-
DEFAULT_TIMEOUT = 30
|
20
|
-
|
21
16
|
# Service error codes
|
22
17
|
# https://docs.microsoft.com/en-us/windows/desktop/debug/system-error-codes--1000-1299-
|
23
18
|
ERROR_SERVICE_DOES_NOT_EXIST = 0x00000424
|
data/lib/puppet/util/windows.rb
CHANGED
data/lib/puppet/util/yaml.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|