diff options
author | Markus Roberts <Markus@reality.com> | 2010-07-09 18:12:17 -0700 |
---|---|---|
committer | Markus Roberts <Markus@reality.com> | 2010-07-09 18:12:17 -0700 |
commit | 3180b9d9b2c844dade1d361326600f7001ec66dd (patch) | |
tree | 98fe7c5ac7eb942aac9c39f019a17b0b3f5a57f4 /lib/puppet/sslcertificates | |
parent | 543225970225de5697734bfaf0a6eee996802c04 (diff) | |
download | puppet-3180b9d9b2c844dade1d361326600f7001ec66dd.tar.gz puppet-3180b9d9b2c844dade1d361326600f7001ec66dd.tar.xz puppet-3180b9d9b2c844dade1d361326600f7001ec66dd.zip |
Code smell: Two space indentation
Replaced 106806 occurances of ^( +)(.*$) with
The ruby community almost universally (i.e. everyone but Luke, Markus, and the other eleven people
who learned ruby in the 1900s) uses two-space indentation.
3 Examples:
The code:
end
# Tell getopt which arguments are valid
def test_get_getopt_args
element = Setting.new :name => "foo", :desc => "anything", :settings => Puppet::Util::Settings.new
assert_equal([["--foo", GetoptLong::REQUIRED_ARGUMENT]], element.getopt_args, "Did not produce appropriate getopt args")
becomes:
end
# Tell getopt which arguments are valid
def test_get_getopt_args
element = Setting.new :name => "foo", :desc => "anything", :settings => Puppet::Util::Settings.new
assert_equal([["--foo", GetoptLong::REQUIRED_ARGUMENT]], element.getopt_args, "Did not produce appropriate getopt args")
The code:
assert_equal(str, val)
assert_instance_of(Float, result)
end
# Now test it with a passed object
becomes:
assert_equal(str, val)
assert_instance_of(Float, result)
end
# Now test it with a passed object
The code:
end
assert_nothing_raised do
klass[:Yay] = "boo"
klass["Cool"] = :yayness
end
becomes:
end
assert_nothing_raised do
klass[:Yay] = "boo"
klass["Cool"] = :yayness
end
Diffstat (limited to 'lib/puppet/sslcertificates')
-rw-r--r-- | lib/puppet/sslcertificates/ca.rb | 646 | ||||
-rw-r--r-- | lib/puppet/sslcertificates/certificate.rb | 376 | ||||
-rw-r--r-- | lib/puppet/sslcertificates/inventory.rb | 54 | ||||
-rw-r--r-- | lib/puppet/sslcertificates/support.rb | 226 |
4 files changed, 651 insertions, 651 deletions
diff --git a/lib/puppet/sslcertificates/ca.rb b/lib/puppet/sslcertificates/ca.rb index e9e66bc61..63e6b922a 100644 --- a/lib/puppet/sslcertificates/ca.rb +++ b/lib/puppet/sslcertificates/ca.rb @@ -1,381 +1,381 @@ require 'sync' class Puppet::SSLCertificates::CA - include Puppet::Util::Warnings + include Puppet::Util::Warnings - Certificate = Puppet::SSLCertificates::Certificate - attr_accessor :keyfile, :file, :config, :dir, :cert, :crl + Certificate = Puppet::SSLCertificates::Certificate + attr_accessor :keyfile, :file, :config, :dir, :cert, :crl - def certfile - @config[:cacert] - end - - # Remove all traces of a given host. This is kind of hackish, but, eh. - def clean(host) - host = host.downcase - [:csrdir, :signeddir, :publickeydir, :privatekeydir, :certdir].each do |name| - dir = Puppet[name] - - file = File.join(dir, host + ".pem") - - if FileTest.exists?(file) - begin - if Puppet[:name] == "cert" - puts "Removing #{file}" - else - Puppet.info "Removing #{file}" - end - File.unlink(file) - rescue => detail - raise Puppet::Error, "Could not delete #{file}: #{detail}" - end - end - - end - end - - def host2csrfile(hostname) - File.join(Puppet[:csrdir], [hostname.downcase, "pem"].join(".")) - end + def certfile + @config[:cacert] + end - # this stores signed certs in a directory unrelated to - # normal client certs - def host2certfile(hostname) - File.join(Puppet[:signeddir], [hostname.downcase, "pem"].join(".")) - end - - # Turn our hostname into a Name object - def thing2name(thing) - thing.subject.to_a.find { |ary| - ary[0] == "CN" - }[1] - end - - def initialize(hash = {}) - Puppet.settings.use(:main, :ca, :ssl) - self.setconfig(hash) - - if Puppet[:capass] - if FileTest.exists?(Puppet[:capass]) - #puts "Reading #{Puppet[:capass]}" - #system "ls -al #{Puppet[:capass]}" - #File.read Puppet[:capass] - @config[:password] = self.getpass - else - # Don't create a password if the cert already exists - @config[:password] = self.genpass unless FileTest.exists?(@config[:cacert]) - end - end - - self.getcert - init_crl - unless FileTest.exists?(@config[:serial]) - Puppet.settings.write(:serial) do |f| - f << "%04X" % 1 - end - end - end + # Remove all traces of a given host. This is kind of hackish, but, eh. + def clean(host) + host = host.downcase + [:csrdir, :signeddir, :publickeydir, :privatekeydir, :certdir].each do |name| + dir = Puppet[name] - # Generate a new password for the CA. - def genpass - pass = "" - 20.times { pass += (rand(74) + 48).chr } + file = File.join(dir, host + ".pem") + if FileTest.exists?(file) begin - Puppet.settings.write(:capass) { |f| f.print pass } - rescue Errno::EACCES => detail - raise Puppet::Error, detail.to_s + if Puppet[:name] == "cert" + puts "Removing #{file}" + else + Puppet.info "Removing #{file}" + end + File.unlink(file) + rescue => detail + raise Puppet::Error, "Could not delete #{file}: #{detail}" end - pass - end + end - # Get the CA password. - def getpass - if @config[:capass] and File.readable?(@config[:capass]) - return File.read(@config[:capass]) - else - raise Puppet::Error, "Could not decrypt CA key with password: #{detail}" - end end - - # Get the CA cert. - def getcert - if FileTest.exists?(@config[:cacert]) - @cert = OpenSSL::X509::Certificate.new( - File.read(@config[:cacert]) - ) - else - self.mkrootcert - end + end + + def host2csrfile(hostname) + File.join(Puppet[:csrdir], [hostname.downcase, "pem"].join(".")) + end + + # this stores signed certs in a directory unrelated to + # normal client certs + def host2certfile(hostname) + File.join(Puppet[:signeddir], [hostname.downcase, "pem"].join(".")) + end + + # Turn our hostname into a Name object + def thing2name(thing) + thing.subject.to_a.find { |ary| + ary[0] == "CN" + }[1] + end + + def initialize(hash = {}) + Puppet.settings.use(:main, :ca, :ssl) + self.setconfig(hash) + + if Puppet[:capass] + if FileTest.exists?(Puppet[:capass]) + #puts "Reading #{Puppet[:capass]}" + #system "ls -al #{Puppet[:capass]}" + #File.read Puppet[:capass] + @config[:password] = self.getpass + else + # Don't create a password if the cert already exists + @config[:password] = self.genpass unless FileTest.exists?(@config[:cacert]) + end end - # Retrieve a client's CSR. - def getclientcsr(host) - csrfile = host2csrfile(host) - return nil unless File.exists?(csrfile) - - OpenSSL::X509::Request.new(File.read(csrfile)) + self.getcert + init_crl + unless FileTest.exists?(@config[:serial]) + Puppet.settings.write(:serial) do |f| + f << "%04X" % 1 + end end + end - # Retrieve a client's certificate. - def getclientcert(host) - certfile = host2certfile(host) - return [nil, nil] unless File.exists?(certfile) + # Generate a new password for the CA. + def genpass + pass = "" + 20.times { pass += (rand(74) + 48).chr } - [OpenSSL::X509::Certificate.new(File.read(certfile)), @cert] + begin + Puppet.settings.write(:capass) { |f| f.print pass } + rescue Errno::EACCES => detail + raise Puppet::Error, detail.to_s end - - # List certificates waiting to be signed. This returns a list of hostnames, not actual - # files -- the names can be converted to full paths with host2csrfile. - def list(dummy_argument=:work_arround_for_ruby_GC_bug) - return Dir.entries(Puppet[:csrdir]).find_all { |file| - file =~ /\.pem$/ - }.collect { |file| - file.sub(/\.pem$/, '') - } + pass + end + + # Get the CA password. + def getpass + if @config[:capass] and File.readable?(@config[:capass]) + return File.read(@config[:capass]) + else + raise Puppet::Error, "Could not decrypt CA key with password: #{detail}" end - - # List signed certificates. This returns a list of hostnames, not actual - # files -- the names can be converted to full paths with host2csrfile. - def list_signed(dummy_argument=:work_arround_for_ruby_GC_bug) - return Dir.entries(Puppet[:signeddir]).find_all { |file| - file =~ /\.pem$/ - }.collect { |file| - file.sub(/\.pem$/, '') - } + end + + # Get the CA cert. + def getcert + if FileTest.exists?(@config[:cacert]) + @cert = OpenSSL::X509::Certificate.new( + File.read(@config[:cacert]) + ) + else + self.mkrootcert + end + end + + # Retrieve a client's CSR. + def getclientcsr(host) + csrfile = host2csrfile(host) + return nil unless File.exists?(csrfile) + + OpenSSL::X509::Request.new(File.read(csrfile)) + end + + # Retrieve a client's certificate. + def getclientcert(host) + certfile = host2certfile(host) + return [nil, nil] unless File.exists?(certfile) + + [OpenSSL::X509::Certificate.new(File.read(certfile)), @cert] + end + + # List certificates waiting to be signed. This returns a list of hostnames, not actual + # files -- the names can be converted to full paths with host2csrfile. + def list(dummy_argument=:work_arround_for_ruby_GC_bug) + return Dir.entries(Puppet[:csrdir]).find_all { |file| + file =~ /\.pem$/ + }.collect { |file| + file.sub(/\.pem$/, '') + } + end + + # List signed certificates. This returns a list of hostnames, not actual + # files -- the names can be converted to full paths with host2csrfile. + def list_signed(dummy_argument=:work_arround_for_ruby_GC_bug) + return Dir.entries(Puppet[:signeddir]).find_all { |file| + file =~ /\.pem$/ + }.collect { |file| + file.sub(/\.pem$/, '') + } + end + + # Create the root certificate. + def mkrootcert + # Make the root cert's name the FQDN of the host running the CA. + name = Facter["hostname"].value + if domain = Facter["domain"].value + name += ".#{domain}" end - # Create the root certificate. - def mkrootcert - # Make the root cert's name the FQDN of the host running the CA. - name = Facter["hostname"].value - if domain = Facter["domain"].value - name += ".#{domain}" - end - - cert = Certificate.new( + cert = Certificate.new( - :name => name, - :cert => @config[:cacert], - :encrypt => @config[:capass], - :key => @config[:cakey], - :selfsign => true, - :ttl => ttl, + :name => name, + :cert => @config[:cacert], + :encrypt => @config[:capass], + :key => @config[:cakey], + :selfsign => true, + :ttl => ttl, - :type => :ca - ) + :type => :ca + ) - # This creates the cakey file - Puppet::Util::SUIDManager.asuser(Puppet[:user], Puppet[:group]) do - @cert = cert.mkselfsigned - end - Puppet.settings.write(:cacert) do |f| - f.puts @cert.to_pem - end - Puppet.settings.write(:capub) do |f| - f.puts @cert.public_key - end - cert + # This creates the cakey file + Puppet::Util::SUIDManager.asuser(Puppet[:user], Puppet[:group]) do + @cert = cert.mkselfsigned end - - def removeclientcsr(host) - csrfile = host2csrfile(host) - raise Puppet::Error, "No certificate request for #{host}" unless File.exists?(csrfile) - - File.unlink(csrfile) + Puppet.settings.write(:cacert) do |f| + f.puts @cert.to_pem end - - # Revoke the certificate with serial number SERIAL issued by this - # CA. The REASON must be one of the OpenSSL::OCSP::REVOKED_* reasons - def revoke(serial, reason = OpenSSL::OCSP::REVOKED_STATUS_KEYCOMPROMISE) - time = Time.now - revoked = OpenSSL::X509::Revoked.new - revoked.serial = serial - revoked.time = time - enum = OpenSSL::ASN1::Enumerated(reason) - ext = OpenSSL::X509::Extension.new("CRLReason", enum) - revoked.add_extension(ext) - @crl.add_revoked(revoked) - store_crl + Puppet.settings.write(:capub) do |f| + f.puts @cert.public_key + end + cert + end + + def removeclientcsr(host) + csrfile = host2csrfile(host) + raise Puppet::Error, "No certificate request for #{host}" unless File.exists?(csrfile) + + File.unlink(csrfile) + end + + # Revoke the certificate with serial number SERIAL issued by this + # CA. The REASON must be one of the OpenSSL::OCSP::REVOKED_* reasons + def revoke(serial, reason = OpenSSL::OCSP::REVOKED_STATUS_KEYCOMPROMISE) + time = Time.now + revoked = OpenSSL::X509::Revoked.new + revoked.serial = serial + revoked.time = time + enum = OpenSSL::ASN1::Enumerated(reason) + ext = OpenSSL::X509::Extension.new("CRLReason", enum) + revoked.add_extension(ext) + @crl.add_revoked(revoked) + store_crl + end + + # Take the Puppet config and store it locally. + def setconfig(hash) + @config = {} + Puppet.settings.params("ca").each { |param| + param = param.intern if param.is_a? String + if hash.include?(param) + @config[param] = hash[param] + Puppet[param] = hash[param] + hash.delete(param) + else + @config[param] = Puppet[param] + end + } + + if hash.include?(:password) + @config[:password] = hash[:password] + hash.delete(:password) end - # Take the Puppet config and store it locally. - def setconfig(hash) - @config = {} - Puppet.settings.params("ca").each { |param| - param = param.intern if param.is_a? String - if hash.include?(param) - @config[param] = hash[param] - Puppet[param] = hash[param] - hash.delete(param) - else - @config[param] = Puppet[param] - end - } - - if hash.include?(:password) - @config[:password] = hash[:password] - hash.delete(:password) - end + raise ArgumentError, "Unknown parameters #{hash.keys.join(",")}" if hash.length > 0 - raise ArgumentError, "Unknown parameters #{hash.keys.join(",")}" if hash.length > 0 + [:cadir, :csrdir, :signeddir].each { |dir| + raise Puppet::DevError, "#{dir} is undefined" unless @config[dir] + } + end - [:cadir, :csrdir, :signeddir].each { |dir| - raise Puppet::DevError, "#{dir} is undefined" unless @config[dir] - } + # Sign a given certificate request. + def sign(csr) + unless csr.is_a?(OpenSSL::X509::Request) + raise Puppet::Error, + "CA#sign only accepts OpenSSL::X509::Request objects, not #{csr.class}" end - # Sign a given certificate request. - def sign(csr) - unless csr.is_a?(OpenSSL::X509::Request) - raise Puppet::Error, - "CA#sign only accepts OpenSSL::X509::Request objects, not #{csr.class}" - end - - raise Puppet::Error, "CSR sign verification failed" unless csr.verify(csr.public_key) + raise Puppet::Error, "CSR sign verification failed" unless csr.verify(csr.public_key) - serial = nil - Puppet.settings.readwritelock(:serial) { |f| - serial = File.read(@config[:serial]).chomp.hex - # increment the serial - f << "%04X" % (serial + 1) - } + serial = nil + Puppet.settings.readwritelock(:serial) { |f| + serial = File.read(@config[:serial]).chomp.hex + # increment the serial + f << "%04X" % (serial + 1) + } - newcert = Puppet::SSLCertificates.mkcert( + newcert = Puppet::SSLCertificates.mkcert( - :type => :server, - :name => csr.subject, - :ttl => ttl, - :issuer => @cert, - :serial => serial, + :type => :server, + :name => csr.subject, + :ttl => ttl, + :issuer => @cert, + :serial => serial, - :publickey => csr.public_key - ) + :publickey => csr.public_key + ) - sign_with_key(newcert) + sign_with_key(newcert) - self.storeclientcert(newcert) + self.storeclientcert(newcert) - [newcert, @cert] - end + [newcert, @cert] + end - # Store the client's CSR for later signing. This is called from - # server/ca.rb, and the CSRs are deleted once the certificate is actually - # signed. - def storeclientcsr(csr) - host = thing2name(csr) + # Store the client's CSR for later signing. This is called from + # server/ca.rb, and the CSRs are deleted once the certificate is actually + # signed. + def storeclientcsr(csr) + host = thing2name(csr) - csrfile = host2csrfile(host) - raise Puppet::Error, "Certificate request for #{host} already exists" if File.exists?(csrfile) + csrfile = host2csrfile(host) + raise Puppet::Error, "Certificate request for #{host} already exists" if File.exists?(csrfile) - Puppet.settings.writesub(:csrdir, csrfile) do |f| - f.print csr.to_pem - end + Puppet.settings.writesub(:csrdir, csrfile) do |f| + f.print csr.to_pem end + end - # Store the certificate that we generate. - def storeclientcert(cert) - host = thing2name(cert) + # Store the certificate that we generate. + def storeclientcert(cert) + host = thing2name(cert) - certfile = host2certfile(host) - Puppet.notice "Overwriting signed certificate #{certfile} for #{host}" if File.exists?(certfile) + certfile = host2certfile(host) + Puppet.notice "Overwriting signed certificate #{certfile} for #{host}" if File.exists?(certfile) - Puppet::SSLCertificates::Inventory::add(cert) - Puppet.settings.writesub(:signeddir, certfile) do |f| - f.print cert.to_pem - end + Puppet::SSLCertificates::Inventory::add(cert) + Puppet.settings.writesub(:signeddir, certfile) do |f| + f.print cert.to_pem end - - # TTL for new certificates in seconds. If config param :ca_ttl is set, - # use that, otherwise use :ca_days for backwards compatibility - def ttl - days = @config[:ca_days] - if days && days.size > 0 - warnonce "Parameter ca_ttl is not set. Using depecated ca_days instead." - return @config[:ca_days] * 24 * 60 * 60 - else - ttl = @config[:ca_ttl] - if ttl.is_a?(String) - unless ttl =~ /^(\d+)(y|d|h|s)$/ - raise ArgumentError, "Invalid ca_ttl #{ttl}" - end - case $2 - when 'y' - unit = 365 * 24 * 60 * 60 - when 'd' - unit = 24 * 60 * 60 - when 'h' - unit = 60 * 60 - when 's' - unit = 1 - else - raise ArgumentError, "Invalid unit for ca_ttl #{ttl}" - end - return $1.to_i * unit - else - return ttl - end + end + + # TTL for new certificates in seconds. If config param :ca_ttl is set, + # use that, otherwise use :ca_days for backwards compatibility + def ttl + days = @config[:ca_days] + if days && days.size > 0 + warnonce "Parameter ca_ttl is not set. Using depecated ca_days instead." + return @config[:ca_days] * 24 * 60 * 60 + else + ttl = @config[:ca_ttl] + if ttl.is_a?(String) + unless ttl =~ /^(\d+)(y|d|h|s)$/ + raise ArgumentError, "Invalid ca_ttl #{ttl}" end - end - - private - def init_crl - if FileTest.exists?(@config[:cacrl]) - @crl = OpenSSL::X509::CRL.new( - File.read(@config[:cacrl]) - ) + case $2 + when 'y' + unit = 365 * 24 * 60 * 60 + when 'd' + unit = 24 * 60 * 60 + when 'h' + unit = 60 * 60 + when 's' + unit = 1 else - # Create new CRL - @crl = OpenSSL::X509::CRL.new - @crl.issuer = @cert.subject - @crl.version = 1 - store_crl - @crl + raise ArgumentError, "Invalid unit for ca_ttl #{ttl}" end + return $1.to_i * unit + else + return ttl + end end - - def store_crl - # Increment the crlNumber - e = @crl.extensions.find { |e| e.oid == 'crlNumber' } - ext = @crl.extensions.reject { |e| e.oid == 'crlNumber' } - crlNum = OpenSSL::ASN1::Integer(e ? e.value.to_i + 1 : 0) - ext << OpenSSL::X509::Extension.new("crlNumber", crlNum) - @crl.extensions = ext - - # Set last/next update - now = Time.now - @crl.last_update = now - # Keep CRL valid for 5 years - @crl.next_update = now + 5 * 365*24*60*60 - - sign_with_key(@crl) - Puppet.settings.write(:cacrl) do |f| - f.puts @crl.to_pem - end + end + + private + def init_crl + if FileTest.exists?(@config[:cacrl]) + @crl = OpenSSL::X509::CRL.new( + File.read(@config[:cacrl]) + ) + else + # Create new CRL + @crl = OpenSSL::X509::CRL.new + @crl.issuer = @cert.subject + @crl.version = 1 + store_crl + @crl + end + end + + def store_crl + # Increment the crlNumber + e = @crl.extensions.find { |e| e.oid == 'crlNumber' } + ext = @crl.extensions.reject { |e| e.oid == 'crlNumber' } + crlNum = OpenSSL::ASN1::Integer(e ? e.value.to_i + 1 : 0) + ext << OpenSSL::X509::Extension.new("crlNumber", crlNum) + @crl.extensions = ext + + # Set last/next update + now = Time.now + @crl.last_update = now + # Keep CRL valid for 5 years + @crl.next_update = now + 5 * 365*24*60*60 + + sign_with_key(@crl) + Puppet.settings.write(:cacrl) do |f| + f.puts @crl.to_pem + end + end + + def sign_with_key(signable, digest = OpenSSL::Digest::SHA1.new) + cakey = nil + if @config[:password] + begin + cakey = OpenSSL::PKey::RSA.new( + File.read(@config[:cakey]), @config[:password] + ) + rescue + raise Puppet::Error, + "Decrypt of CA private key with password stored in @config[:capass] not possible" + end + else + cakey = OpenSSL::PKey::RSA.new( + File.read(@config[:cakey]) + ) end - def sign_with_key(signable, digest = OpenSSL::Digest::SHA1.new) - cakey = nil - if @config[:password] - begin - cakey = OpenSSL::PKey::RSA.new( - File.read(@config[:cakey]), @config[:password] - ) - rescue - raise Puppet::Error, - "Decrypt of CA private key with password stored in @config[:capass] not possible" - end - else - cakey = OpenSSL::PKey::RSA.new( - File.read(@config[:cakey]) - ) - end - - raise Puppet::Error, "CA Certificate is invalid" unless @cert.check_private_key(cakey) + raise Puppet::Error, "CA Certificate is invalid" unless @cert.check_private_key(cakey) - signable.sign(cakey, digest) - end + signable.sign(cakey, digest) + end end diff --git a/lib/puppet/sslcertificates/certificate.rb b/lib/puppet/sslcertificates/certificate.rb index a9d1dd4ea..2d30bb09f 100644 --- a/lib/puppet/sslcertificates/certificate.rb +++ b/lib/puppet/sslcertificates/certificate.rb @@ -1,148 +1,148 @@ class Puppet::SSLCertificates::Certificate - SSLCertificates = Puppet::SSLCertificates - - attr_accessor :certfile, :keyfile, :name, :dir, :hash, :type - attr_accessor :key, :cert, :csr, :cacert - - @@params2names = { - :name => "CN", - :state => "ST", - :country => "C", - :email => "emailAddress", - :org => "O", - :city => "L", - :ou => "OU" + SSLCertificates = Puppet::SSLCertificates + + attr_accessor :certfile, :keyfile, :name, :dir, :hash, :type + attr_accessor :key, :cert, :csr, :cacert + + @@params2names = { + :name => "CN", + :state => "ST", + :country => "C", + :email => "emailAddress", + :org => "O", + :city => "L", + :ou => "OU" + } + + def certname + OpenSSL::X509::Name.new self.subject + end + + def delete + [@certfile,@keyfile].each { |file| + File.unlink(file) if FileTest.exists?(file) } - def certname - OpenSSL::X509::Name.new self.subject + if @hash + File.unlink(@hash) if FileTest.symlink?(@hash) end + end - def delete - [@certfile,@keyfile].each { |file| - File.unlink(file) if FileTest.exists?(file) - } - - if @hash - File.unlink(@hash) if FileTest.symlink?(@hash) - end - end + def exists? + FileTest.exists?(@certfile) + end - def exists? - FileTest.exists?(@certfile) - end - - def getkey - self.mkkey unless FileTest.exists?(@keyfile) - if @password + def getkey + self.mkkey unless FileTest.exists?(@keyfile) + if @password - @key = OpenSSL::PKey::RSA.new( + @key = OpenSSL::PKey::RSA.new( - File.read(@keyfile), + File.read(@keyfile), - @password - ) - else - @key = OpenSSL::PKey::RSA.new( - File.read(@keyfile) - ) - end + @password + ) + else + @key = OpenSSL::PKey::RSA.new( + File.read(@keyfile) + ) end + end - def initialize(hash) - raise Puppet::Error, "You must specify the common name for the certificate" unless hash.include?(:name) - @name = hash[:name] - - # init a few variables - @cert = @key = @csr = nil + def initialize(hash) + raise Puppet::Error, "You must specify the common name for the certificate" unless hash.include?(:name) + @name = hash[:name] - if hash.include?(:cert) - @certfile = hash[:cert] - @dir = File.dirname(@certfile) - else - @dir = hash[:dir] || Puppet[:certdir] - @certfile = File.join(@dir, @name) - end + # init a few variables + @cert = @key = @csr = nil - @cacertfile ||= File.join(Puppet[:certdir], "ca.pem") + if hash.include?(:cert) + @certfile = hash[:cert] + @dir = File.dirname(@certfile) + else + @dir = hash[:dir] || Puppet[:certdir] + @certfile = File.join(@dir, @name) + end - Puppet.recmkdir(@dir) unless FileTest.directory?(@dir) + @cacertfile ||= File.join(Puppet[:certdir], "ca.pem") - unless @certfile =~ /\.pem$/ - @certfile += ".pem" - end - @keyfile = hash[:key] || File.join( - Puppet[:privatekeydir], [@name,"pem"].join(".") - ) - Puppet.recmkdir(@dir) unless FileTest.directory?(@dir) + Puppet.recmkdir(@dir) unless FileTest.directory?(@dir) - [@keyfile].each { |file| - dir = File.dirname(file) + unless @certfile =~ /\.pem$/ + @certfile += ".pem" + end + @keyfile = hash[:key] || File.join( + Puppet[:privatekeydir], [@name,"pem"].join(".") + ) + Puppet.recmkdir(@dir) unless FileTest.directory?(@dir) - Puppet.recmkdir(dir) unless FileTest.directory?(dir) - } + [@keyfile].each { |file| + dir = File.dirname(file) - @ttl = hash[:ttl] || 365 * 24 * 60 * 60 - @selfsign = hash[:selfsign] || false - @encrypt = hash[:encrypt] || false - @replace = hash[:replace] || false - @issuer = hash[:issuer] || nil - - if hash.include?(:type) - case hash[:type] - when :ca, :client, :server; @type = hash[:type] - else - raise "Invalid Cert type #{hash[:type]}" - end - else - @type = :client - end + Puppet.recmkdir(dir) unless FileTest.directory?(dir) + } - @params = {:name => @name} - [:state, :country, :email, :org, :ou].each { |param| - @params[param] = hash[param] if hash.include?(param) - } + @ttl = hash[:ttl] || 365 * 24 * 60 * 60 + @selfsign = hash[:selfsign] || false + @encrypt = hash[:encrypt] || false + @replace = hash[:replace] || false + @issuer = hash[:issuer] || nil + + if hash.include?(:type) + case hash[:type] + when :ca, :client, :server; @type = hash[:type] + else + raise "Invalid Cert type #{hash[:type]}" + end + else + @type = :client + end - if @encrypt - if @encrypt =~ /^\// - File.open(@encrypt) { |f| - @password = f.read.chomp - } - else - raise Puppet::Error, ":encrypt must be a path to a pass phrase file" - end - else - @password = nil - end + @params = {:name => @name} + [:state, :country, :email, :org, :ou].each { |param| + @params[param] = hash[param] if hash.include?(param) + } - @selfsign = hash.include?(:selfsign) && hash[:selfsign] + if @encrypt + if @encrypt =~ /^\// + File.open(@encrypt) { |f| + @password = f.read.chomp + } + else + raise Puppet::Error, ":encrypt must be a path to a pass phrase file" + end + else + @password = nil end - # this only works for servers, not for users - def mkcsr - self.getkey unless @key + @selfsign = hash.include?(:selfsign) && hash[:selfsign] + end - name = OpenSSL::X509::Name.new self.subject + # this only works for servers, not for users + def mkcsr + self.getkey unless @key - @csr = OpenSSL::X509::Request.new - @csr.version = 0 - @csr.subject = name - @csr.public_key = @key.public_key - @csr.sign(@key, OpenSSL::Digest::SHA1.new) + name = OpenSSL::X509::Name.new self.subject - #File.open(@csrfile, "w") { |f| - # f << @csr.to_pem - #} + @csr = OpenSSL::X509::Request.new + @csr.version = 0 + @csr.subject = name + @csr.public_key = @key.public_key + @csr.sign(@key, OpenSSL::Digest::SHA1.new) - raise Puppet::Error, "CSR sign verification failed" unless @csr.verify(@key.public_key) + #File.open(@csrfile, "w") { |f| + # f << @csr.to_pem + #} - @csr - end + raise Puppet::Error, "CSR sign verification failed" unless @csr.verify(@key.public_key) - def mkkey - # @key is the file + @csr + end - @key = OpenSSL::PKey::RSA.new(1024) + def mkkey + # @key is the file + + @key = OpenSSL::PKey::RSA.new(1024) # { |p,n| # case p # when 0; Puppet.info "key info: ." # BN_generate_prime @@ -156,100 +156,100 @@ class Puppet::SSLCertificates::Certificate # end # } - if @password - # passwdproc = proc { @password } - - keytext = @key.export( + if @password + # passwdproc = proc { @password } - OpenSSL::Cipher::DES.new(:EDE3, :CBC), + keytext = @key.export( - @password - ) - File.open(@keyfile, "w", 0400) { |f| - f << keytext - } - else - File.open(@keyfile, "w", 0400) { |f| - f << @key.to_pem - } - end + OpenSSL::Cipher::DES.new(:EDE3, :CBC), - #cmd = "#{ossl} genrsa -out #{@key} 1024" + @password + ) + File.open(@keyfile, "w", 0400) { |f| + f << keytext + } + else + File.open(@keyfile, "w", 0400) { |f| + f << @key.to_pem + } end - def mkselfsigned - self.getkey unless @key + #cmd = "#{ossl} genrsa -out #{@key} 1024" + end - raise Puppet::Error, "Cannot replace existing certificate" if @cert + def mkselfsigned + self.getkey unless @key - args = { - :name => self.certname, - :ttl => @ttl, - :issuer => nil, - :serial => 0x0, - :publickey => @key.public_key - } - if @type - args[:type] = @type - else - args[:type] = :server - end - @cert = SSLCertificates.mkcert(args) + raise Puppet::Error, "Cannot replace existing certificate" if @cert - @cert.sign(@key, OpenSSL::Digest::SHA1.new) if @selfsign - - @cert + args = { + :name => self.certname, + :ttl => @ttl, + :issuer => nil, + :serial => 0x0, + :publickey => @key.public_key + } + if @type + args[:type] = @type + else + args[:type] = :server end + @cert = SSLCertificates.mkcert(args) - def subject(string = false) - subj = @@params2names.collect { |param, name| - [name, @params[param]] if @params.include?(param) - }.reject { |ary| ary.nil? } + @cert.sign(@key, OpenSSL::Digest::SHA1.new) if @selfsign - if string - return "/" + subj.collect { |ary| - "%s=%s" % ary - }.join("/") + "/" - else - return subj - end - end + @cert + end - # verify that we can track down the cert chain or whatever - def verify - "openssl verify -verbose -CAfile /home/luke/.puppet/ssl/certs/ca.pem -purpose sslserver culain.madstop.com.pem" + def subject(string = false) + subj = @@params2names.collect { |param, name| + [name, @params[param]] if @params.include?(param) + }.reject { |ary| ary.nil? } + + if string + return "/" + subj.collect { |ary| + "%s=%s" % ary + }.join("/") + "/" + else + return subj end + end - def write - files = { - @certfile => @cert, - @keyfile => @key, - } - files[@cacertfile] = @cacert if defined?(@cacert) + # verify that we can track down the cert chain or whatever + def verify + "openssl verify -verbose -CAfile /home/luke/.puppet/ssl/certs/ca.pem -purpose sslserver culain.madstop.com.pem" + end - files.each { |file,thing| - if thing - next if FileTest.exists?(file) + def write + files = { + @certfile => @cert, + @keyfile => @key, + } + files[@cacertfile] = @cacert if defined?(@cacert) - text = nil + files.each { |file,thing| + if thing + next if FileTest.exists?(file) - if thing.is_a?(OpenSSL::PKey::RSA) and @password + text = nil - text = thing.export( + if thing.is_a?(OpenSSL::PKey::RSA) and @password - OpenSSL::Cipher::DES.new(:EDE3, :CBC), + text = thing.export( - @password - ) - else - text = thing.to_pem - end + OpenSSL::Cipher::DES.new(:EDE3, :CBC), - File.open(file, "w", 0660) { |f| f.print text } - end - } + @password + ) + else + text = thing.to_pem + end - SSLCertificates.mkhash(Puppet[:certdir], @cacert, @cacertfile) if defined?(@cacert) - end + File.open(file, "w", 0660) { |f| f.print text } + end + } + + SSLCertificates.mkhash(Puppet[:certdir], @cacert, @cacertfile) if defined?(@cacert) + end end diff --git a/lib/puppet/sslcertificates/inventory.rb b/lib/puppet/sslcertificates/inventory.rb index c3f79ee6c..1075c1377 100644 --- a/lib/puppet/sslcertificates/inventory.rb +++ b/lib/puppet/sslcertificates/inventory.rb @@ -1,38 +1,38 @@ # 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 + 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 self.add(cert) - inited = false - inited = true if FileTest.exists?(Puppet[:cert_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 self.add(cert) + inited = false + inited = true if FileTest.exists?(Puppet[:cert_inventory]) - Puppet.settings.write(:cert_inventory, "a") do |f| - f.puts((inited ? nil : self.init).to_s + format(cert)) - end - end + Puppet.settings.write(:cert_inventory, "a") do |f| + f.puts((inited ? nil : self.init).to_s + format(cert)) + end + end - private + private - def self.init - inv = "# Inventory of signed certificates\n" - inv += "# SERIAL NOT_BEFORE NOT_AFTER SUBJECT\n" - Dir.glob(File::join(Puppet[:signeddir], "*.pem")) do |f| - inv += format(OpenSSL::X509::Certificate.new(File::read(f))) + "\n" - end - inv - end + def self.init + inv = "# Inventory of signed certificates\n" + inv += "# SERIAL NOT_BEFORE NOT_AFTER SUBJECT\n" + Dir.glob(File::join(Puppet[:signeddir], "*.pem")) do |f| + inv += format(OpenSSL::X509::Certificate.new(File::read(f))) + "\n" + end + inv + end - def self.format(cert) - iso = '%Y-%m-%dT%H:%M:%S%Z' - return "0x%04x %s %s %s" % [cert.serial, - cert.not_before.strftime(iso), - cert.not_after.strftime(iso), - cert.subject] - end + def self.format(cert) + iso = '%Y-%m-%dT%H:%M:%S%Z' + return "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/lib/puppet/sslcertificates/support.rb b/lib/puppet/sslcertificates/support.rb index 919d68664..7d6708124 100644 --- a/lib/puppet/sslcertificates/support.rb +++ b/lib/puppet/sslcertificates/support.rb @@ -2,145 +2,145 @@ require 'puppet/sslcertificates' # A module to handle reading of certificates. module Puppet::SSLCertificates::Support - class MissingCertificate < Puppet::Error; end - class InvalidCertificate < Puppet::Error; end + class MissingCertificate < Puppet::Error; end + class InvalidCertificate < Puppet::Error; end - attr_reader :cacert + attr_reader :cacert - # Some metaprogramming to create methods for retrieving and creating keys. - # This probably isn't fewer lines than defining each separately... - def self.keytype(name, options, &block) - var = "@#{name}" + # Some metaprogramming to create methods for retrieving and creating keys. + # This probably isn't fewer lines than defining each separately... + def self.keytype(name, options, &block) + var = "@#{name}" - maker = "mk_#{name}" - reader = "read_#{name}" + maker = "mk_#{name}" + reader = "read_#{name}" - unless param = options[:param] - raise ArgumentError, "You must specify the parameter for the key" - end - - unless klass = options[:class] - raise ArgumentError, "You must specify the class for the key" - end + unless param = options[:param] + raise ArgumentError, "You must specify the parameter for the key" + end - # Define the method that creates it. - define_method(maker, &block) + unless klass = options[:class] + raise ArgumentError, "You must specify the class for the key" + end - # Define the reading method. - define_method(reader) do - return nil unless FileTest.exists?(Puppet[param]) or rename_files_with_uppercase(Puppet[param]) + # Define the method that creates it. + define_method(maker, &block) - begin - instance_variable_set(var, klass.new(File.read(Puppet[param]))) - rescue => detail - raise InvalidCertificate, "Could not read #{param}: #{detail}" - end - end + # Define the reading method. + define_method(reader) do + return nil unless FileTest.exists?(Puppet[param]) or rename_files_with_uppercase(Puppet[param]) - # Define the overall method, which just calls the reader and maker - # as appropriate. - define_method(name) do - unless cert = instance_variable_get(var) - unless cert = send(reader) - cert = send(maker) - Puppet.settings.write(param) { |f| f.puts cert.to_pem } - end - instance_variable_set(var, cert) - end - cert - end + begin + instance_variable_set(var, klass.new(File.read(Puppet[param]))) + rescue => detail + raise InvalidCertificate, "Could not read #{param}: #{detail}" + end end - # The key pair. - keytype :key, :param => :hostprivkey, :class => OpenSSL::PKey::RSA do - Puppet.info "Creating a new SSL key at #{Puppet[:hostprivkey]}" - key = OpenSSL::PKey::RSA.new(Puppet[:keylength]) - - # Our key meta programming can only handle one file, so we have - # to separately write out the public key. - Puppet.settings.write(:hostpubkey) do |f| - f.print key.public_key.to_pem + # Define the overall method, which just calls the reader and maker + # as appropriate. + define_method(name) do + unless cert = instance_variable_get(var) + unless cert = send(reader) + cert = send(maker) + Puppet.settings.write(param) { |f| f.puts cert.to_pem } end - return key + instance_variable_set(var, cert) + end + cert end + end - # Our certificate request - keytype :csr, :param => :hostcsr, :class => OpenSSL::X509::Request do - Puppet.info "Creating a new certificate request for #{Puppet[:certname]}" + # The key pair. + keytype :key, :param => :hostprivkey, :class => OpenSSL::PKey::RSA do + Puppet.info "Creating a new SSL key at #{Puppet[:hostprivkey]}" + key = OpenSSL::PKey::RSA.new(Puppet[:keylength]) - csr = OpenSSL::X509::Request.new - csr.version = 0 - csr.subject = OpenSSL::X509::Name.new([["CN", Puppet[:certname]]]) - csr.public_key = key.public_key - csr.sign(key, OpenSSL::Digest::MD5.new) - - return csr + # Our key meta programming can only handle one file, so we have + # to separately write out the public key. + Puppet.settings.write(:hostpubkey) do |f| + f.print key.public_key.to_pem end - - keytype :cert, :param => :hostcert, :class => OpenSSL::X509::Certificate do - raise MissingCertificate, "No host certificate" + return key + end + + # Our certificate request + keytype :csr, :param => :hostcsr, :class => OpenSSL::X509::Request do + Puppet.info "Creating a new certificate request for #{Puppet[:certname]}" + + csr = OpenSSL::X509::Request.new + csr.version = 0 + csr.subject = OpenSSL::X509::Name.new([["CN", Puppet[:certname]]]) + csr.public_key = key.public_key + csr.sign(key, OpenSSL::Digest::MD5.new) + + return csr + end + + keytype :cert, :param => :hostcert, :class => OpenSSL::X509::Certificate do + raise MissingCertificate, "No host certificate" + end + + keytype :ca_cert, :param => :localcacert, :class => OpenSSL::X509::Certificate do + raise MissingCertificate, "No CA certificate" + end + + # Request a certificate from the remote system. This does all of the work + # of creating the cert request, contacting the remote system, and + # storing the cert locally. + def requestcert + begin + cert, cacert = caclient.getcert(@csr.to_pem) + rescue => detail + puts detail.backtrace if Puppet[:trace] + raise Puppet::Error.new("Certificate retrieval failed: #{detail}") end - keytype :ca_cert, :param => :localcacert, :class => OpenSSL::X509::Certificate do - raise MissingCertificate, "No CA certificate" + if cert.nil? or cert == "" + return nil end - - # Request a certificate from the remote system. This does all of the work - # of creating the cert request, contacting the remote system, and - # storing the cert locally. - def requestcert - begin - cert, cacert = caclient.getcert(@csr.to_pem) - rescue => detail - puts detail.backtrace if Puppet[:trace] - raise Puppet::Error.new("Certificate retrieval failed: #{detail}") - end - - if cert.nil? or cert == "" - return nil - end - Puppet.settings.write(:hostcert) do |f| f.print cert end - Puppet.settings.write(:localcacert) do |f| f.print cacert end - #File.open(@certfile, "w", 0644) { |f| f.print cert } - #File.open(@cacertfile, "w", 0644) { |f| f.print cacert } - begin - @cert = OpenSSL::X509::Certificate.new(cert) - @cacert = OpenSSL::X509::Certificate.new(cacert) - retrieved = true - rescue => detail - raise Puppet::Error.new( - "Invalid certificate: #{detail}" - ) - end - - raise Puppet::DevError, "Received invalid certificate" unless @cert.check_private_key(@key) - retrieved + Puppet.settings.write(:hostcert) do |f| f.print cert end + Puppet.settings.write(:localcacert) do |f| f.print cacert end + #File.open(@certfile, "w", 0644) { |f| f.print cert } + #File.open(@cacertfile, "w", 0644) { |f| f.print cacert } + begin + @cert = OpenSSL::X509::Certificate.new(cert) + @cacert = OpenSSL::X509::Certificate.new(cacert) + retrieved = true + rescue => detail + raise Puppet::Error.new( + "Invalid certificate: #{detail}" + ) end - # A hack method to deal with files that exist with a different case. - # Just renames it; doesn't read it in or anything. - def rename_files_with_uppercase(file) - dir = File.dirname(file) - short = File.basename(file) + raise Puppet::DevError, "Received invalid certificate" unless @cert.check_private_key(@key) + retrieved + end - # If the dir isn't present, we clearly don't have the file. - #return nil unless FileTest.directory?(dir) + # A hack method to deal with files that exist with a different case. + # Just renames it; doesn't read it in or anything. + def rename_files_with_uppercase(file) + dir = File.dirname(file) + short = File.basename(file) - raise ArgumentError, "Tried to fix SSL files to a file containing uppercase" unless short.downcase == short + # If the dir isn't present, we clearly don't have the file. + #return nil unless FileTest.directory?(dir) - return false unless File.directory?(dir) + raise ArgumentError, "Tried to fix SSL files to a file containing uppercase" unless short.downcase == short - real_file = Dir.entries(dir).reject { |f| f =~ /^\./ }.find do |other| - other.downcase == short - end + return false unless File.directory?(dir) - return nil unless real_file + real_file = Dir.entries(dir).reject { |f| f =~ /^\./ }.find do |other| + other.downcase == short + end - full_file = File.join(dir, real_file) + return nil unless real_file - Puppet.notice "Fixing case in #{full_file}; renaming to #{file}" - File.rename(full_file, file) + full_file = File.join(dir, real_file) - true - end + Puppet.notice "Fixing case in #{full_file}; renaming to #{file}" + File.rename(full_file, file) + + true + end end |