# File lib/puppet/sslcertificates.rb, line 13
 13:     def self.mkcert(hash)
 14:         [:type, :name, :ttl, :issuer, :serial, :publickey].each { |param|
 15:             unless hash.include?(param)
 16:                 raise ArgumentError, "mkcert called without %s" % param
 17:             end
 18:         }
 19: 
 20:         cert = OpenSSL::X509::Certificate.new
 21:         # Make the certificate valid as of yesterday, because
 22:         # so many people's clocks are out of sync.
 23:         from = Time.now - (60*60*24)
 24: 
 25:         cert.subject = hash[:name]
 26:         if hash[:issuer]
 27:             cert.issuer = hash[:issuer].subject
 28:         else
 29:             # we're a self-signed cert
 30:             cert.issuer = hash[:name]
 31:         end
 32:         cert.not_before = from
 33:         cert.not_after = from + hash[:ttl]
 34:         cert.version = 2 # X509v3
 35: 
 36:         cert.public_key = hash[:publickey]
 37:         cert.serial = hash[:serial]
 38: 
 39:         basic_constraint = nil
 40:         key_usage = nil
 41:         ext_key_usage = nil
 42:         subject_alt_name = []
 43: 
 44:         ef = OpenSSL::X509::ExtensionFactory.new
 45: 
 46:         ef.subject_certificate = cert
 47: 
 48:         if hash[:issuer]
 49:             ef.issuer_certificate = hash[:issuer]
 50:         else
 51:             ef.issuer_certificate = cert
 52:         end
 53: 
 54:         ex = []
 55:         case hash[:type]
 56:         when :ca
 57:             basic_constraint = "CA:TRUE"
 58:             key_usage = %w{cRLSign keyCertSign}
 59:         when :terminalsubca
 60:             basic_constraint = "CA:TRUE,pathlen:0"
 61:             key_usage = %w{cRLSign keyCertSign}
 62:         when :server
 63:             basic_constraint = "CA:FALSE"
 64:             dnsnames = Puppet[:certdnsnames]
 65:             name = hash[:name].to_s.sub(%r{/CN=},'')
 66:             if dnsnames != ""
 67:                 dnsnames.split(':').each { |d| subject_alt_name << 'DNS:' + d }
 68:                 subject_alt_name << 'DNS:' + name # Add the fqdn as an alias
 69:             elsif name == Facter.value(:fqdn) # we're a CA server, and thus probably the server
 70:                 subject_alt_name << 'DNS:' + "puppet" # Add 'puppet' as an alias
 71:                 subject_alt_name << 'DNS:' + name # Add the fqdn as an alias
 72:                 subject_alt_name << 'DNS:' + name.sub(/^[^.]+./, "puppet.") # add puppet.domain as an alias
 73:             end
 74:             key_usage = %w{digitalSignature keyEncipherment}
 75:             ext_key_usage = %w{serverAuth clientAuth emailProtection}
 76:         when :ocsp
 77:             basic_constraint = "CA:FALSE"
 78:             key_usage = %w{nonRepudiation digitalSignature}
 79:             ext_key_usage = %w{serverAuth OCSPSigning}
 80:         when :client
 81:             basic_constraint = "CA:FALSE"
 82:             key_usage = %w{nonRepudiation digitalSignature keyEncipherment}
 83:             ext_key_usage = %w{clientAuth emailProtection}
 84:             ex << ef.create_extension("nsCertType", "client,email")
 85:         else
 86:             raise Puppet::Error, "unknown cert type '%s'" % hash[:type]
 87:         end
 88: 
 89:         ex << ef.create_extension("nsComment",
 90:                                   "Puppet Ruby/OpenSSL Generated Certificate")
 91:         ex << ef.create_extension("basicConstraints", basic_constraint, true)
 92:         ex << ef.create_extension("subjectKeyIdentifier", "hash")
 93: 
 94:         ex << ef.create_extension("keyUsage", key_usage.join(",")) if key_usage
 95:         ex << ef.create_extension("extendedKeyUsage", ext_key_usage.join(",")) if ext_key_usage
 96:         ex << ef.create_extension("subjectAltName", subject_alt_name.join(",")) if ! subject_alt_name.empty?
 97: 
 98:         #if @ca_config[:cdp_location] then
 99:         #  ex << ef.create_extension("crlDistributionPoints",
100:         #                            @ca_config[:cdp_location])
101:         #end
102: 
103:         #if @ca_config[:ocsp_location] then
104:         #  ex << ef.create_extension("authorityInfoAccess",
105:         #                            "OCSP;" << @ca_config[:ocsp_location])
106:         #end
107:         cert.extensions = ex
108: 
109:         # for some reason this _must_ be the last extension added
110:         ex << ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always") if hash[:type] == :ca
111: 
112:         return cert
113:     end