summaryrefslogtreecommitdiffstats
path: root/lib/puppet/sslcertificates/certificate.rb
diff options
context:
space:
mode:
authorluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-01-24 06:01:58 +0000
committerluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-01-24 06:01:58 +0000
commitae2575b45de1e8f4c0ec956cebe0eed2bafbcf57 (patch)
tree9c2b7c839087c285c228374f525315e55c392a34 /lib/puppet/sslcertificates/certificate.rb
parent18e8e74a2e3b4c5d092fc0aae38bbc5455d4db48 (diff)
downloadpuppet-ae2575b45de1e8f4c0ec956cebe0eed2bafbcf57.tar.gz
puppet-ae2575b45de1e8f4c0ec956cebe0eed2bafbcf57.tar.xz
puppet-ae2575b45de1e8f4c0ec956cebe0eed2bafbcf57.zip
Adding the event-loop stuff to the repository and switching to using it. Also, breaking many classes out into their own class files.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@848 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib/puppet/sslcertificates/certificate.rb')
-rw-r--r--lib/puppet/sslcertificates/certificate.rb283
1 files changed, 283 insertions, 0 deletions
diff --git a/lib/puppet/sslcertificates/certificate.rb b/lib/puppet/sslcertificates/certificate.rb
new file mode 100644
index 000000000..65ceb44b9
--- /dev/null
+++ b/lib/puppet/sslcertificates/certificate.rb
@@ -0,0 +1,283 @@
+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"
+ }
+
+ def certname
+ OpenSSL::X509::Name.new self.subject
+ end
+
+ def delete
+ [@certfile,@keyfile].each { |file|
+ if FileTest.exists?(file)
+ File.unlink(file)
+ end
+ }
+
+ if defined? @hash and @hash
+ if FileTest.symlink?(@hash)
+ File.unlink(@hash)
+ end
+ end
+ end
+
+ def exists?
+ return FileTest.exists?(@certfile)
+ end
+
+ def getkey
+ unless FileTest.exists?(@keyfile)
+ self.mkkey()
+ end
+ if @password
+ @key = OpenSSL::PKey::RSA.new(
+ File.read(@keyfile),
+ @password
+ )
+ else
+ @key = OpenSSL::PKey::RSA.new(
+ File.read(@keyfile)
+ )
+ end
+ end
+
+ def initialize(hash)
+ unless hash.include?(:name)
+ raise "You must specify the common name for the certificate"
+ end
+ @name = hash[:name]
+
+ # init a few variables
+ @cert = @key = @csr = nil
+
+ if hash.include?(:cert)
+ @certfile = hash[:cert]
+ @dir = File.dirname(@certfile)
+ else
+ @dir = hash[:dir] || Puppet[:certdir]
+ @certfile = File.join(@dir, @name)
+ end
+
+ @cacertfile ||= File.join(Puppet[:certdir], "ca.pem")
+
+ unless FileTest.directory?(@dir)
+ Puppet::SSLCertificates.mkdir(@dir)
+ end
+
+ unless @certfile =~ /\.pem$/
+ @certfile += ".pem"
+ end
+ @keyfile = hash[:key] || File.join(
+ Puppet[:privatekeydir], [@name,"pem"].join(".")
+ )
+ unless FileTest.directory?(@dir)
+ Puppet::SSLCertificates.mkdir(@dir)
+ end
+
+ [@keyfile].each { |file|
+ dir = File.dirname(file)
+
+ unless FileTest.directory?(dir)
+ Puppet::SSLCertificates.mkdir(dir)
+ end
+ }
+
+ @days = hash[:length] || 365
+ @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 %s" % hash[:type]
+ end
+ else
+ @type = :client
+ end
+
+ @params = {:name => @name}
+ [:state, :country, :email, :org, :ou].each { |param|
+ if hash.include?(param)
+ @params[param] = hash[param]
+ end
+ }
+
+ if @encrypt
+ if @encrypt =~ /^\//
+ File.open(@encrypt) { |f|
+ @password = f.read.chomp
+ }
+ else
+ raise ":encrypt must be a path to a pass phrase file"
+ end
+ else
+ @password = nil
+ end
+
+ if hash.include?(:selfsign)
+ @selfsign = hash[:selfsign]
+ else
+ @selfsign = false
+ end
+ end
+
+ # this only works for servers, not for users
+ def mkcsr
+ unless defined? @key and @key
+ self.getkey
+ end
+
+ name = OpenSSL::X509::Name.new self.subject
+
+ @csr = OpenSSL::X509::Request.new
+ @csr.version = 0
+ @csr.subject = name
+ @csr.public_key = @key.public_key
+ @csr.sign(@key, OpenSSL::Digest::SHA1.new)
+
+ #File.open(@csrfile, "w") { |f|
+ # f << @csr.to_pem
+ #}
+
+ unless @csr.verify(@key.public_key)
+ raise Puppet::Error, "CSR sign verification failed"
+ end
+
+ return @csr
+ end
+
+ 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
+# when 1; Puppet.info "key info: +" # BN_generate_prime
+# when 2; Puppet.info "key info: *" # searching good prime,
+# # n = #of try,
+# # but also data from BN_generate_prime
+# when 3; Puppet.info "key info: \n" # found good prime, n==0 - p, n==1 - q,
+# # but also data from BN_generate_prime
+# else; Puppet.info "key info: *" # BN_generate_prime
+# end
+# }
+
+ if @password
+ #passwdproc = proc { @password }
+ keytext = @key.export(
+ OpenSSL::Cipher::DES.new(:EDE3, :CBC),
+ @password
+ )
+ File.open(@keyfile, "w", 0400) { |f|
+ f << keytext
+ }
+ else
+ File.open(@keyfile, "w", 0400) { |f|
+ f << @key.to_pem
+ }
+ end
+
+ #cmd = "#{ossl} genrsa -out #{@key} 1024"
+ end
+
+ def mkselfsigned
+ unless defined? @key and @key
+ self.getkey
+ end
+
+ if defined? @cert and @cert
+ raise Puppet::Error, "Cannot replace existing certificate"
+ end
+
+ args = {
+ :name => self.certname,
+ :days => @days,
+ :issuer => nil,
+ :serial => 0x0,
+ :publickey => @key.public_key
+ }
+ if @type
+ args[:type] = @type
+ else
+ args[:type] = :server
+ end
+ @cert = SSLCertificates.mkcert(args)
+
+ @cert.sign(@key, OpenSSL::Digest::SHA1.new) if @selfsign
+
+ return @cert
+ end
+
+ def subject(string = false)
+ subj = @@params2names.collect { |param, name|
+ if @params.include?(param)
+ [name, @params[param]]
+ end
+ }.reject { |ary| ary.nil? }
+
+ if string
+ return "/" + subj.collect { |ary|
+ "%s=%s" % ary
+ }.join("/") + "/"
+ else
+ return subj
+ end
+ 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"
+ end
+
+ def write
+ files = {
+ @certfile => @cert,
+ @keyfile => @key,
+ }
+ if defined? @cacert
+ files[@cacertfile] = @cacert
+ end
+
+ files.each { |file,thing|
+ if defined? thing and thing
+ if FileTest.exists?(file)
+ next
+ end
+
+ text = nil
+
+ if thing.is_a?(OpenSSL::PKey::RSA) and @password
+ text = thing.export(
+ OpenSSL::Cipher::DES.new(:EDE3, :CBC),
+ @password
+ )
+ else
+ text = thing.to_pem
+ end
+
+ File.open(file, "w", 0660) { |f| f.print text }
+ end
+ }
+
+ if defined? @cacert
+ SSLCertificates.mkhash(Puppet[:certdir], @cacert, @cacertfile)
+ end
+ end
+end
+
+# $Id$