Uploaded image for project: 'Puppet'
  1. Puppet
  2. PUP-5469

Indirector YAML terminii don't validate their return values

    XMLWordPrintable

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.

      Attachments

        Activity

          People

            Unassigned Unassigned
            chuck Charlie Sharpsteen
            Eric Thompson Eric Thompson
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Zendesk Support