summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlutter <lutter@980ebf18-57e1-0310-9a29-db15c13687c0>2006-08-23 02:23:25 +0000
committerlutter <lutter@980ebf18-57e1-0310-9a29-db15c13687c0>2006-08-23 02:23:25 +0000
commit9576d1dda88bd14490b91f7aee0dbaee28969f79 (patch)
treed4098b1438093658920e777d290d0e658f0458d5
parent4151fd59ef6490c875140a874c0a13c5d3f311aa (diff)
downloadpuppet-9576d1dda88bd14490b91f7aee0dbaee28969f79.tar.gz
puppet-9576d1dda88bd14490b91f7aee0dbaee28969f79.tar.xz
puppet-9576d1dda88bd14490b91f7aee0dbaee28969f79.zip
Certificate revocation through puppetca. Keep a simple text inventory of all certificates ever issued.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@1485 980ebf18-57e1-0310-9a29-db15c13687c0
-rwxr-xr-xbin/puppetca49
-rwxr-xr-xlib/puppet/sslcertificates.rb1
-rw-r--r--lib/puppet/sslcertificates/ca.rb1
-rw-r--r--lib/puppet/sslcertificates/inventory.rb49
-rwxr-xr-xtest/executables/puppetca.rb23
5 files changed, 114 insertions, 9 deletions
diff --git a/bin/puppetca b/bin/puppetca
index f725e4a8f..d694ba294 100755
--- a/bin/puppetca
+++ b/bin/puppetca
@@ -46,6 +46,14 @@
# list::
# List outstanding certificate requests.
#
+# revoke::
+# Revoke the certificate of a client. The certificate can be specified
+# either by its serial number, given as a decimal number or a hexadecimal
+# number prefixed by '0x', or by its hostname. The certificate is revoked
+# by adding it to the Certificate Revocation List given by the 'cacrl'
+# config parameter. Note that the puppetmasterd needs to be restarted
+# after revoking certificates.
+#
# sign::
# Sign an outstanding certificate request. Unless '--all' is specified,
# hosts must be listed after all flags.
@@ -81,14 +89,15 @@ rescue LoadError
end
options = [
- [ "--all", "-a", GetoptLong::NO_ARGUMENT ],
- [ "--clean", "-c", GetoptLong::NO_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 ],
- [ "--verbose", "-v", GetoptLong::NO_ARGUMENT ]
+ [ "--all", "-a", GetoptLong::NO_ARGUMENT ],
+ [ "--clean", "-c", GetoptLong::NO_ARGUMENT ],
+ [ "--debug", "-d", GetoptLong::NO_ARGUMENT ],
+ [ "--generate", "-g", GetoptLong::NO_ARGUMENT ],
+ [ "--help", "-h", GetoptLong::NO_ARGUMENT ],
+ [ "--list", "-l", GetoptLong::NO_ARGUMENT ],
+ [ "--revoke", "-r", GetoptLong::NO_ARGUMENT ],
+ [ "--sign", "-s", GetoptLong::NO_ARGUMENT ],
+ [ "--verbose", "-v", GetoptLong::NO_ARGUMENT ]
]
# Add all of the config parameters as valid options.
@@ -121,6 +130,8 @@ begin
end
when "--list"
mode = :list
+ when "--revoke"
+ mode = :revoke
when "--sign"
mode = :sign
when "--verbose"
@@ -160,7 +171,7 @@ unless mode
exit(12)
end
-if mode == :generate or mode == :clean
+if mode == :generate or mode == :clean or mode == :revoke
hosts = ARGV
else
hosts = ca.list
@@ -230,6 +241,26 @@ when :generate
cert.cacert = cacert
cert.write
}
+when :revoke
+ hosts.each { |h|
+ serial = nil
+ if h =~ /^0x[0-9a-f]+$/
+ serial = h.to_i(16)
+ elsif h =~ /^[0-9]+$/
+ serial = h.to_i
+ else
+ cert = ca.getclientcert(h)[0]
+ if cert.nil?
+ $stderr.puts "Could not find client certificate for %s" % h
+ else
+ serial = cert.serial
+ end
+ end
+ unless serial.nil?
+ ca.revoke(serial)
+ puts "Revoked certificate with serial #{serial}"
+ end
+ }
else
$stderr.puts "Invalid mode %s" % mode
exit(42)
diff --git a/lib/puppet/sslcertificates.rb b/lib/puppet/sslcertificates.rb
index a003c6551..4df8df71e 100755
--- a/lib/puppet/sslcertificates.rb
+++ b/lib/puppet/sslcertificates.rb
@@ -154,6 +154,7 @@ module Puppet::SSLCertificates
return hashpath
end
require 'puppet/sslcertificates/certificate'
+ require 'puppet/sslcertificates/inventory'
require 'puppet/sslcertificates/ca'
end
diff --git a/lib/puppet/sslcertificates/ca.rb b/lib/puppet/sslcertificates/ca.rb
index 89b7b183c..1574a6e73 100644
--- a/lib/puppet/sslcertificates/ca.rb
+++ b/lib/puppet/sslcertificates/ca.rb
@@ -346,6 +346,7 @@ class Puppet::SSLCertificates::CA
[certfile, host]
end
+ Puppet::SSLCertificates::Inventory::add(cert)
Puppet.config.writesub(:signeddir, certfile) do |f|
f.print cert.to_pem
end
diff --git a/lib/puppet/sslcertificates/inventory.rb b/lib/puppet/sslcertificates/inventory.rb
new file mode 100644
index 000000000..f3f790906
--- /dev/null
+++ b/lib/puppet/sslcertificates/inventory.rb
@@ -0,0 +1,49 @@
+# A module for keeping track of all the certificates issued by the CA, ever
+# Maintains the file "$cadir/inventory.txt"
+module Puppet::SSLCertificates
+ module Inventory
+
+ # Add CERT to the inventory of issued certs in '$cadir/inventory.txt'
+ # If no inventory exists yet, build an inventory and list all the
+ # certificates that have been signed so far
+ def Inventory.add(cert)
+ f = open
+ format(f, cert)
+ f.close()
+ end
+
+ def Inventory.filename
+ File::join(Puppet[:cadir], "inventory.txt")
+ end
+
+ private
+ def Inventory.open
+ if File::exist?(filename)
+ File::open(filename, "a")
+ else
+ init
+ end
+ end
+
+ def Inventory.init
+ if File::exist?(filename)
+ raise Puppet::Error,
+ "Inventory file #{filename} already exists"
+ end
+ inv = File.open(filename, "w")
+ inv.puts "# Inventory of signed certificates"
+ Dir.glob(File::join(Puppet[:signeddir], "*.pem")) do |f|
+ format(inv, OpenSSL::X509::Certificate.new(File::read(f)))
+ end
+ return inv
+ end
+
+ def Inventory.format(f, cert)
+ iso = '%Y-%m-%dT%H:%M:%S%Z'
+ f.puts "0x%04x %s %s %s" % [cert.serial,
+ cert.not_before.strftime(iso),
+ cert.not_after.strftime(iso),
+ cert.subject]
+ end
+ end
+end
diff --git a/test/executables/puppetca.rb b/test/executables/puppetca.rb
index b722c963f..71764ebd2 100755
--- a/test/executables/puppetca.rb
+++ b/test/executables/puppetca.rb
@@ -84,6 +84,29 @@ class TestPuppetCA < Test::Unit::TestCase
assert_equal($?,0)
assert_equal(["No certificates to sign"], output)
end
+
+ def test_revocation
+ ca = Puppet::SSLCertificates::CA.new()
+ host1 = gen_cert(ca, "host1.example.com")
+ host2 = gen_cert(ca, "host2.example.com")
+ host3 = gen_cert(ca, "host3.example.com")
+ runca("-r host1.example.com")
+ runca("-r #{host2.serial}")
+ runca("-r 0x#{host3.serial.to_s(16)}")
+ runca("-r 0xff")
+
+ # Recreate CA to force reading of CRL
+ ca = Puppet::SSLCertificates::CA.new()
+ crl = ca.crl
+ revoked = crl.revoked.collect { |r| r.serial }
+ exp = [host1.serial, host2.serial, host3.serial, 255]
+ assert_equal(exp, revoked)
+ end
+
+ def gen_cert(ca, host)
+ runca("-g #{host}")
+ ca.getclientcert(host)[0]
+ end
end
# $Id$