Details
-
Bug
-
Status: Closed
-
Normal
-
Resolution: Won't Fix
-
PUP 3.8.4, PUP 4.2.3
-
None
-
None
Description
Puppet uses the YAML indirector terminii to cache various pieces of data. Catalog compilation relies on this terminus to maintain the state of agent facts during operations such as node retrieval. If facts cannot be read from the cache, the compiler will fall back to retrieving them from PuppetDB which triggers PUP-5441 and can result in a catalog that was compiled using stale information.
The YAML terminii do not perform any validation to ensure an oject of the proper type is being returned from the cache. Thus, if something adjusts the behavior of Ruby YAML serialization and deserialization, compilation will start failing with cryptic errors or, in some cases, continue on without the user receiving any indication that outdated facts are being used.
Reproduction Case
- Install a PE 2015.2 monolithic master.
- Add the safe_yaml gem to the Puppet Server: /opt/puppetlabs/bin/puppetserver gem install safe_yaml
- Simulate a Puppet plugin that loads safe_yaml by adding an inline_template call to the site manifest of the production environment:
node default { |
$foo = inline_template('<% require "safe_yaml" %>') |
}
|
This will
Outcome
The first catalog compilation will succeed:
# puppet agent -t
|
Info: Retrieving pluginfacts
|
Info: Retrieving plugin
|
Info: Loading facts
|
Info: Caching catalog for pe-201522-master.puppetdebug.vlan
|
Info: Applying configuration version '1446582492'
|
Subsequent compilations will fail because safe_yaml has been loaded which causes the Ruby YAML libary to start returning plain hashes instead of Puppet::Indirector::Yaml instances:
# puppet agent -t
|
Info: Retrieving pluginfacts
|
Info: Retrieving plugin
|
Info: Loading facts
|
Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Attempt to assign to a reserved variable name: 'trusted' on node pe-201522-master.puppetdebug.vlan
|
Warning: Not using cache on failed catalog
|
Error: Could not retrieve catalog; skipping run
|
The only indication of trouble is an error message recorded in the Puppet Server logs:
2015-11-03 20:45:05,507 DEBUG [puppet-server] Puppet Caching environment 'production' (ttl = 0 sec)
|
2015-11-03 20:45:05,554 ERROR [puppet-server] Puppet Cached facts for pe-201522-agent.puppetdebug.vlan failed: undefined method `expired?' for #<Hash:0x353d56da>
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/indirector/indirection.rb:228:in `find_in_cache'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/indirector/indirection.rb:186:in `find'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/node.rb:108:in `fact_merge'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/indirector/node/classifier.rb:104:in `retrieve_classification'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/indirector/node/classifier.rb:44:in `find'
|
org/jruby/RubyArray.java:1613:in `each'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/indirector/node/classifier.rb:43:in `find'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/indirector/indirection.rb:194:in `find'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:109:in `find_node'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:106:in `find_node'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:146:in `node_from_request'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:47:in `find'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/indirector/indirection.rb:194:in `find'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/network/http/api/indirected_routes.rb:134:in `do_find'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/network/http/api/indirected_routes.rb:48:in `call'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/context.rb:64:in `override'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet.rb:234:in `override'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/network/http/api/indirected_routes.rb:47:in `call'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/network/http/route.rb:82:in `process'
|
org/jruby/RubyArray.java:1613:in `each'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/network/http/route.rb:81:in `process'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/network/http/route.rb:87:in `process'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/network/http/route.rb:87:in `process'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/network/http/handler.rb:60:in `process'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
|
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/network/http/handler.rb:58:in `process'
|
file:/opt/puppetlabs/server/apps/puppetserver/puppet-server-release.jar!/puppet-server-lib/puppet/server/master.rb:39:in `handleRequest'
|
Puppet$$Server$$Master_1555992597.gen:13:in `handleRequest'
|
request_handler_core.clj:274:in `invoke'
|
request_handler_service.clj:14:in `handle_request'
|
request_handler.clj:3:in `invoke'
|
request_handler.clj:3:in `invoke'
|
core.clj:626:in `invoke'
|
core.clj:2468:in `doInvoke'
|
master_core.clj:47:in `invoke'
|
ring.clj:22:in `invoke'
|
ring.clj:13:in `invoke'
|
comidi.clj:267:in `invoke'
|
ringutils.clj:106:in `invoke'
|
ringutils.clj:62:in `invoke'
|
ringutils.clj:68:in `invoke'
|
ringutils.clj:118:in `invoke'
|
http.clj:152:in `invoke'
|
http.clj:152:in `invoke'
|
http.clj:148:in `invoke'
|
comidi.clj:314:in `invoke'
|
jetty9_core.clj:408:in `invoke'
|
2015-11-03 20:45:05,678 INFO [puppet-server] Puppet Caching facts for pe-201522-agent.puppetdebug.vlan
|
2015-11-03 20:45:05,694 INFO [puppet-server] Puppet Caching node for pe-201522-agent.puppetdebug.vlan
|
2015-11-03 20:45:05,721 ERROR [puppet-server] Puppet Attempt to assign to a reserved variable name: 'trusted' on node pe-201522-agent.puppetdebug.vlan
|
Expected Outcome
Subclasses of Puppet::Indirector::Yaml explicitly create objects from cached data rather than relying on YAML parser magic.