Home > Tech HowTos > Puppet problems with hostname in autosign.conf – Invalid pattern

Puppet problems with hostname in autosign.conf – Invalid pattern

October 14th, 2009

In playing with Puppet (0.24.8 on clients and server) today (well, building a new host) I came by a strange error when I ran puppet on the client:

err: Could not request certificate: Certificate retrieval failed: Invalid pattern css-storemanager

The thing that was so strange is that “css-storemanager” is the name of a host at my site, controlled by Puppet, but it has nothing to do with the host I was building. They’re different boxes, on different subnets, in different rooms. One is a SunFire and the other is an HP desktop.

Google turned up nothing. Running puppetmasterd with --debug --trace yielded:

info: Listening on port 8140
notice: Starting Puppet server version 0.24.8
notice: Allowing unauthenticated client ccf-hill019-12.example.edu(172.x.x.x) access to puppetca.getcert
/usr/lib/ruby/site_ruby/1.8/puppet/network/authstore.rb:289:in `parse'
/usr/lib/ruby/site_ruby/1.8/puppet/network/authstore.rb:170:in `pattern='
/usr/lib/ruby/site_ruby/1.8/puppet/network/authstore.rb:151:in `initialize'
/usr/lib/ruby/site_ruby/1.8/puppet/network/authstore.rb:80:in `new'
/usr/lib/ruby/site_ruby/1.8/puppet/network/authstore.rb:80:in `store'
/usr/lib/ruby/site_ruby/1.8/puppet/network/authstore.rb:20:in `allow'
/usr/lib/ruby/site_ruby/1.8/puppet/network/handler/ca.rb:54:in `autosign?'
/usr/lib/ruby/site_ruby/1.8/puppet/network/handler/ca.rb:51:in `each'
/usr/lib/ruby/site_ruby/1.8/puppet/network/handler/ca.rb:51:in `autosign?'
/usr/lib/ruby/site_ruby/1.8/puppet/network/handler/ca.rb:50:in `open'
/usr/lib/ruby/site_ruby/1.8/puppet/network/handler/ca.rb:50:in `autosign?'
/usr/lib/ruby/site_ruby/1.8/puppet/network/handler/ca.rb:112:in `getcert'
/usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `to_proc'
/usr/lib/ruby/site_ruby/1.8/puppet/network/xmlrpc/processor.rb:52:in `call'
/usr/lib/ruby/site_ruby/1.8/puppet/network/xmlrpc/processor.rb:52:in `protect_service'
/usr/lib/ruby/site_ruby/1.8/puppet/network/xmlrpc/processor.rb:85:in `setup_processor'
/usr/lib/ruby/1.8/xmlrpc/server.rb:336:in `call'
/usr/lib/ruby/1.8/xmlrpc/server.rb:336:in `dispatch'
/usr/lib/ruby/1.8/xmlrpc/server.rb:323:in `each'
/usr/lib/ruby/1.8/xmlrpc/server.rb:323:in `dispatch'
/usr/lib/ruby/1.8/xmlrpc/server.rb:366:in `call_method'
/usr/lib/ruby/1.8/xmlrpc/server.rb:378:in `handle'
/usr/lib/ruby/site_ruby/1.8/puppet/network/xmlrpc/processor.rb:44:in `process'
/usr/lib/ruby/site_ruby/1.8/puppet/network/xmlrpc/webrick_servlet.rb:68:in `service'
/usr/lib/ruby/1.8/webrick/httpserver.rb:104:in `service'
/usr/lib/ruby/1.8/webrick/httpserver.rb:65:in `run'
/usr/lib/ruby/1.8/webrick/server.rb:173:in `start_thread'
/usr/lib/ruby/1.8/webrick/server.rb:162:in `start'
/usr/lib/ruby/1.8/webrick/server.rb:162:in `start_thread'
/usr/lib/ruby/1.8/webrick/server.rb:95:in `start'
/usr/lib/ruby/1.8/webrick/server.rb:92:in `each'
/usr/lib/ruby/1.8/webrick/server.rb:92:in `start'
/usr/lib/ruby/1.8/webrick/server.rb:23:in `start'
/usr/lib/ruby/1.8/webrick/server.rb:82:in `start'
/usr/lib/ruby/site_ruby/1.8/puppet.rb:293:in `start'
/usr/lib/ruby/site_ruby/1.8/puppet.rb:144:in `newthread'
/usr/lib/ruby/site_ruby/1.8/puppet.rb:143:in `initialize'
/usr/lib/ruby/site_ruby/1.8/puppet.rb:143:in `new'
/usr/lib/ruby/site_ruby/1.8/puppet.rb:143:in `newthread'
/usr/lib/ruby/site_ruby/1.8/puppet.rb:291:in `start'
/usr/lib/ruby/site_ruby/1.8/puppet.rb:290:in `each'
/usr/lib/ruby/site_ruby/1.8/puppet.rb:290:in `start'
/usr/sbin/puppetmasterd:285
err: Invalid pattern css-storemanager

After a bit of investigation into that trace, I found the following code in /usr/lib/ruby/site_ruby/1.8/puppet/network/authstore.rb starting on line 242:

242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
            # Parse our input pattern and figure out what kind of allowal
            # statement it is.  The output of this is used for later matching.
            def parse(value)
                case value
                when /^(\d+\.){1,3}\*$/: # an ip address with a '*' at the end
                    @name = :ip
                    match = $1
                    match.sub!(".", '')
                    ary = value.split(".")
 
                    mask = case ary.index(match)
                    when 0: 8
                    when 1: 16
                    when 2: 24
                    else
                        raise AuthStoreError, "Invalid IP pattern %s" % value
                    end
 
                    @length = mask
 
                    ary.pop
                    while ary.length < 4
                        ary.push("0")
                    end
 
                    begin
                        @pattern = IPAddr.new(ary.join(".") + "/" + mask.to_s)
                    rescue ArgumentError => detail
                        raise AuthStoreError, "Invalid IP address pattern %s" % value
                    end
                when /^([a-zA-Z][-\w]*\.)+[-\w]+$/: # a full hostname
                    @name = :domain
                    @pattern = munge_name(value)
                when /^\*(\.([a-zA-Z][-\w]*)){1,}$/: # *.domain.com
                    @name = :domain
                    @pattern = munge_name(value)
                    @pattern.pop # take off the '*'
                    @length = @pattern.length
                else
                    # Else, use the IPAddr class to determine if we've got a
                    # valid IP address.
                    if value =~ /\/(\d+)$/
                        @length = Integer($1)
                    end
                    begin
                        @pattern = IPAddr.new(value)
                    rescue ArgumentError => detail
                        raise AuthStoreError, "Invalid pattern %s" % value
                    end
                    @name = :ip
                end

Following the trace back, I took a look at /usr/lib/ruby/site_ruby/1.8/puppet/network/handler/ca.rb starting at line 50:

50
51
52
53
54
55
56
57
            auth = Puppet::Network::AuthStore.new
            File.open(autosign) { |f|
                f.each { |line|
                    next if line =~ /^\s*#/
                    next if line =~ /^\s*$/
                    auth.allow(line.chomp)
                }
            }

After looking at this, it clicked that it must be what evaluates autosign.conf. Taking a look at mine, one line stood out: a line containing only “css-storemanager”, not a FQDN like all the rest. The parse() function in authstore.rb only accepts IP addresses and FQDNs (or IP addresses ending in a wildcard, or wildcard FQDNs). It appears to choke on hostnames (a string that doesn’t match an FQDN or IP). Interestingly, it also evaluates in order, and stops evaluating autosign.conf once it finds a match. So, if you’re a Bad Person like me, and left autosign turned on for all of your hosts, you wouldn’t notice this until you try and build a new box.

To solve this, just remove any offending lines from autosign.conf.

I’ve filed a bug report on the Puppet Trac: Issue 2723.

Tech HowTos

  1. No comments yet.
  1. No trackbacks yet.