File: //proc/self/root/usr/lib/ruby/site_ruby/1.8/puppet/ssl/certificate_authority/interface.rb
module Puppet
module SSL
class CertificateAuthority
# This class is basically a hidden class that knows how to act on the
# CA. Its job is to provide a CLI-like interface to the CA class.
class Interface
INTERFACE_METHODS = [:destroy, :list, :revoke, :generate, :sign, :print, :verify, :fingerprint, :reinventory]
SUBJECTLESS_METHODS = [:list, :reinventory]
class InterfaceError < ArgumentError; end
attr_reader :method, :subjects, :digest, :options
# Actually perform the work.
def apply(ca)
unless subjects || SUBJECTLESS_METHODS.include?(method)
raise ArgumentError, "You must provide hosts or --all when using #{method}"
end
# if the interface implements the method, use it instead of the ca's method
if respond_to?(method)
send(method, ca)
else
(subjects == :all ? ca.list : subjects).each do |host|
ca.send(method, host)
end
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, options)
end
end
def initialize(method, options)
self.method = method
self.subjects = options.delete(:to)
@digest = options.delete(:digest)
@options = options
end
# List the hosts.
def list(ca)
signed = ca.list if [:signed, :all].include?(subjects)
requests = ca.waiting?
case subjects
when :all
hosts = [signed, requests].flatten
when :signed
hosts = signed.flatten
when nil
hosts = requests
else
hosts = subjects
signed = ca.list(hosts)
end
certs = {:signed => {}, :invalid => {}, :request => {}}
return if hosts.empty?
hosts.uniq.sort.each do |host|
begin
ca.verify(host) unless requests.include?(host)
rescue Puppet::SSL::CertificateAuthority::CertificateVerificationError => details
verify_error = details.to_s
end
if verify_error
certs[:invalid][host] = [ Puppet::SSL::Certificate.indirection.find(host), verify_error ]
elsif (signed and signed.include?(host))
certs[:signed][host] = Puppet::SSL::Certificate.indirection.find(host)
else
certs[:request][host] = Puppet::SSL::CertificateRequest.indirection.find(host)
end
end
names = certs.values.map(&:keys).flatten
name_width = names.sort_by(&:length).last.length rescue 0
# We quote these names, so account for those characters
name_width += 2
output = [:request, :signed, :invalid].map do |type|
next if certs[type].empty?
certs[type].map do |host,info|
format_host(ca, host, type, info, name_width)
end
end.flatten.compact.sort.join("\n")
puts output
end
def format_host(ca, host, type, info, width)
cert, verify_error = info
alt_names = case type
when :signed
cert.subject_alt_names
when :request
cert.subject_alt_names
else
[]
end
alt_names.delete(host)
alt_str = "(alt names: #{alt_names.map(&:inspect).join(', ')})" unless alt_names.empty?
glyph = {:signed => '+', :request => ' ', :invalid => '-'}[type]
name = host.inspect.ljust(width)
fingerprint = cert.digest(@digest).to_s
explanation = "(#{verify_error})" if verify_error
[glyph, name, fingerprint, alt_str, explanation].compact.join(' ')
end
# Set the method to apply.
def method=(method)
raise ArgumentError, "Invalid method #{method} to apply" 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 #{host}"
end
end
end
# Print certificate information.
def fingerprint(ca)
(subjects == :all ? ca.list + ca.waiting?: subjects).each do |host|
if cert = (Puppet::SSL::Certificate.indirection.find(host) || Puppet::SSL::CertificateRequest.indirection.find(host))
puts "#{host} #{cert.digest(@digest)}"
else
Puppet.err "Could not find certificate for #{host}"
end
end
end
# Signs given certificates or waiting of subjects == :all
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, options[:allow_dns_alt_names])
end
end
def reinventory(ca)
ca.inventory.rebuild
end
# Set the list of hosts we're operating on. Also supports keywords.
def subjects=(value)
unless value == :all || value == :signed || value.is_a?(Array)
raise ArgumentError, "Subjects must be an array or :all; not #{value}"
end
@subjects = (value == []) ? nil : value
end
end
end
end
end