summaryrefslogtreecommitdiffstats
path: root/lib/puppet
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2008-04-19 19:08:36 -0500
committerLuke Kanies <luke@madstop.com>2008-04-19 19:08:36 -0500
commitebdbe4880d8c20965ac21a473b2bfc1ab953b6d4 (patch)
tree3ad90a8ef93313f95db4f2976bd043c4f8fe7640 /lib/puppet
parent934fbba81cb18f05e07675d79a2e830c4e95c918 (diff)
downloadpuppet-ebdbe4880d8c20965ac21a473b2bfc1ab953b6d4.tar.gz
puppet-ebdbe4880d8c20965ac21a473b2bfc1ab953b6d4.tar.xz
puppet-ebdbe4880d8c20965ac21a473b2bfc1ab953b6d4.zip
Added an Interface class to the CA to model puppetca's usage.
This class provides all of the semantics from puppetca, and appears to entirely duplicate the behaviour of the existing executable, with basically all of the code in a library file, instead of the executable. As such, I've deleted the test for the executable. We should have one, but it's not nearly as important.
Diffstat (limited to 'lib/puppet')
-rw-r--r--lib/puppet/ssl/certificate_authority.rb121
-rw-r--r--lib/puppet/ssl/certificate_revocation_list.rb1
2 files changed, 122 insertions, 0 deletions
diff --git a/lib/puppet/ssl/certificate_authority.rb b/lib/puppet/ssl/certificate_authority.rb
index 2399c7204..8785ee5b0 100644
--- a/lib/puppet/ssl/certificate_authority.rb
+++ b/lib/puppet/ssl/certificate_authority.rb
@@ -14,8 +14,129 @@ class Puppet::SSL::CertificateAuthority
require 'puppet/ssl/inventory'
require 'puppet/ssl/certificate_revocation_list'
+ # This class is basically a hidden class that knows how to act
+ # on the CA. It's only used by the 'puppetca' executable, and its
+ # job is to provide a CLI-like interface to the CA class.
+ class Interface
+ INTERFACE_METHODS = [:destroy, :list, :revoke, :generate, :sign, :print, :verify]
+
+ class InterfaceError < ArgumentError; end
+
+ attr_reader :method, :subjects
+
+ # Actually perform the work.
+ def apply(ca)
+ unless subjects or method == :list
+ raise ArgumentError, "You must provide hosts or :all when using %s" % method
+ end
+
+ begin
+ if respond_to?(method)
+ return send(method, ca)
+ end
+
+ (subjects == :all ? ca.list : subjects).each do |host|
+ ca.send(method, host)
+ end
+ rescue InterfaceError
+ raise
+ rescue => detail
+ puts detail.backtrace if Puppet[:trace]
+ Puppet.err "Could not call %s: %s" % [method, detail]
+ end
+ end
+
+ def generate(ca)
+ raise InterfaceError, "It makes no sense to generate all hosts; you must specify a list" if subjects == :all
+
+ subjects.each do |host|
+ ca.generate(host)
+ end
+ end
+
+ def initialize(method, subjects)
+ self.method = method
+ self.subjects = subjects
+ end
+
+ # List the hosts.
+ def list(ca)
+ unless subjects
+ puts ca.waiting?.join("\n")
+ return nil
+ end
+
+ signed = ca.list
+ requests = ca.waiting?
+
+ if subjects == :all
+ hosts = [signed, requests].flatten
+ else
+ hosts = subjects
+ end
+
+ hosts.uniq.sort.each do |host|
+ if signed.include?(host)
+ puts "+ " + host
+ else
+ puts host
+ end
+ end
+ end
+
+ # Set the method to apply.
+ def method=(method)
+ raise ArgumentError, "Invalid method %s to apply" % method unless INTERFACE_METHODS.include?(method)
+ @method = method
+ end
+
+ # Print certificate information.
+ def print(ca)
+ (subjects == :all ? ca.list : subjects).each do |host|
+ if value = ca.print(host)
+ puts value
+ else
+ Puppet.err "Could not find certificate for %s" % host
+ end
+ end
+ end
+
+ # Sign a given certificate.
+ def sign(ca)
+ list = subjects == :all ? ca.waiting? : subjects
+ raise InterfaceError, "No waiting certificate requests to sign" if list.empty?
+ list.each do |host|
+ ca.sign(host)
+ end
+ end
+
+ # Set the list of hosts we're operating on. Also supports keywords.
+ def subjects=(value)
+ unless value == :all or value.is_a?(Array)
+ raise ArgumentError, "Subjects must be an array or :all; not %s" % value
+ end
+
+ if value.is_a?(Array) and value.empty?
+ value = nil
+ end
+
+ @subjects = value
+ end
+ end
+
attr_reader :name, :host
+ # Create and run an applicator. I wanted to build an interface where you could do
+ # something like 'ca.apply(:generate).to(:all) but I don't think it's really possible.
+ def apply(method, options)
+ unless options[:to]
+ raise ArgumentError, "You must specify the hosts to apply to; valid values are an array or the symbol :all"
+ end
+ applier = Interface.new(method, options[:to])
+
+ applier.apply(self)
+ end
+
# Retrieve (or create, if necessary) the certificate revocation list.
def crl
unless defined?(@crl)
diff --git a/lib/puppet/ssl/certificate_revocation_list.rb b/lib/puppet/ssl/certificate_revocation_list.rb
index ca7b7db65..96b71c7a3 100644
--- a/lib/puppet/ssl/certificate_revocation_list.rb
+++ b/lib/puppet/ssl/certificate_revocation_list.rb
@@ -30,6 +30,7 @@ class Puppet::SSL::CertificateRevocationList < Puppet::SSL::Base
# CA, then write the CRL back to disk. The REASON must be one of the
# OpenSSL::OCSP::REVOKED_* reasons
def revoke(serial, cakey, reason = OpenSSL::OCSP::REVOKED_STATUS_KEYCOMPROMISE)
+ Puppet.notice "Revoked certificate with serial %s" % serial
time = Time.now
# Add our revocation to the CRL.