#!/usr/bin/ruby # # = Synopsis # # Stand-alone certificate authority. Capable of generating certificates # but mostly meant for signing certificate requests from puppet clients. # # = Usage # # puppetca [-h|--help] [-V|--version] [-d|--debug] [-v|--verbose] # [--cadir ] [-g|--generate] [-l|--list] # [-s|--sign] [--ssldir ] # [-c|--confdir ] # # = Description # # Because the puppetmasterd daemon defaults to not signing client certificate # requests, this script is available for signing outstanding requests. It # can be used to list outstanding requests and then either sign them individually # or sign all of them. # # = Options # # all:: # Operate on all outstanding requests. Only makes sense with '--sign'. # # cadir:: # Where to look for the ca directory. Defaults to /etc/puppet/ssl/ca. # # confdir:: # The configuration root directory, where +puppetmasterd+ defaults to looking # for all of its configuration files. Defaults to +/etc/puppet+. # # debug:: # Enable full debugging. # # generate:: # Generate a certificate for a named client. A certificate/keypair will be # generated for each client named on the command line. # # help:: # Print this help message # # list:: # List outstanding certificate requests. # # sign:: # Sign an outstanding certificate request. Unless '--all' is specified, # hosts must be listed after all flags. # # ssldir:: # The directory in which to store certificates. Defaults to /etc/puppet/ssl. # # verbose:: # Enable verbosity. # # = Example # # $ puppetca -l # culain.madstop.com # $ puppetca -s culain.madstop.com # # = Author # # Luke Kanies # # = Copyright # # Copyright (c) 2005 Reductive Labs, LLC # Licensed under the GNU Public License require 'puppet' require 'puppet/sslcertificates' require 'getoptlong' $haveusage = true begin require 'rdoc/usage' rescue LoadError $haveusage = false end result = GetoptLong.new( [ "--all", "-a", GetoptLong::NO_ARGUMENT ], [ "--cadir", GetoptLong::REQUIRED_ARGUMENT ], [ "--confdir", "-c", GetoptLong::REQUIRED_ARGUMENT ], [ "--debug", "-d", GetoptLong::NO_ARGUMENT ], [ "--generate", "-g", GetoptLong::NO_ARGUMENT ], [ "--help", "-h", GetoptLong::NO_ARGUMENT ], [ "--list", "-l", GetoptLong::NO_ARGUMENT ], [ "--sign", "-s", GetoptLong::NO_ARGUMENT ], [ "--ssldir", GetoptLong::REQUIRED_ARGUMENT ], [ "--verbose", "-v", GetoptLong::NO_ARGUMENT ] ) mode = nil all = false generate = nil begin result.each { |opt,arg| case opt when "--all" all = true when "--cadir" Puppet[:cadir] = arg when "--confdir" Puppet[:puppetconf] = arg when "--debug" Puppet[:loglevel] = :debug when "--generate" generate = arg mode = :generate when "--help" if $haveusage RDoc::usage && exit else puts "No help available unless you have RDoc::usage installed" exit end when "--list" mode = :list when "--sign" mode = :sign when "--ssldir" Puppet[:ssldir] = arg when "--verbose" Puppet[:loglevel] = :info end } rescue GetoptLong::InvalidOption => detail $stderr.puts "Try '#{$0} --help'" #if $haveusage # RDoc::usage_no_exit('usage') #end exit(1) end ca = Puppet::SSLCertificates::CA.new() unless mode $stderr.puts "You must specify --list or --sign" exit(12) end hosts = ca.list unless hosts.length > 0 or mode == :generate Puppet.info "No waiting requests" exit(0) end case mode when :list puts hosts.join("\n") when :sign unless ARGV.length > 0 or all $stderr.puts( "You must specify to sign all certificates or you must specify hostnames" ) exit(24) end unless all hosts = hosts.find_all { |host| ARGV.include?(host) } end hosts.each { |host| begin csr = ca.getclientcsr(host) rescue => detail $stderr.puts "Could not retrieve request for %s: %s" % [host, detail] end begin ca.sign(csr) rescue => detail $stderr.puts "Could not sign request for %s: %s" % [host, detail] end begin ca.removeclientcsr(host) rescue => detail $stderr.puts "Could not remove request for %s: %s" % [host, detail] end } when :generate # we need to generate a certificate for a host unless ARGV.length > 0 $stderr.puts "You must specify hosts to generate certs for" exit(84) end ARGV.each { |host| puts "Generating certificate for %s" % host cert = Puppet::SSLCertificates::Certificate.new( :name => host ) cert.mkcsr signedcert, cacert = ca.sign(cert.csr) cert.cert = signedcert cert.cacert = cacert cert.write } else $stderr.puts "Invalid mode %s" % mode exit(42) end # $Id$