9: def self.mkcert(hash)
10: [:type, :name, :ttl, :issuer, :serial, :publickey].each { |param|
11: raise ArgumentError, "mkcert called without #{param}" unless hash.include?(param)
12: }
13:
14: cert = OpenSSL::X509::Certificate.new
15:
16:
17: from = Time.now - (60*60*24)
18:
19: cert.subject = hash[:name]
20: if hash[:issuer]
21: cert.issuer = hash[:issuer].subject
22: else
23:
24: cert.issuer = hash[:name]
25: end
26: cert.not_before = from
27: cert.not_after = from + hash[:ttl]
28: cert.version = 2
29:
30: cert.public_key = hash[:publickey]
31: cert.serial = hash[:serial]
32:
33: basic_constraint = nil
34: key_usage = nil
35: ext_key_usage = nil
36: subject_alt_name = []
37:
38: ef = OpenSSL::X509::ExtensionFactory.new
39:
40: ef.subject_certificate = cert
41:
42: if hash[:issuer]
43: ef.issuer_certificate = hash[:issuer]
44: else
45: ef.issuer_certificate = cert
46: end
47:
48: ex = []
49: case hash[:type]
50: when :ca
51: basic_constraint = "CA:TRUE"
52: key_usage = %w{cRLSign keyCertSign}
53: when :terminalsubca
54: basic_constraint = "CA:TRUE,pathlen:0"
55: key_usage = %w{cRLSign keyCertSign}
56: when :server
57: basic_constraint = "CA:FALSE"
58: dnsnames = Puppet[:certdnsnames]
59: name = hash[:name].to_s.sub(%r{/CN=},'')
60: if dnsnames != ""
61: dnsnames.split(':').each { |d| subject_alt_name << 'DNS:' + d }
62: subject_alt_name << 'DNS:' + name
63: elsif name == Facter.value(:fqdn)
64: subject_alt_name << 'DNS:' + "puppet"
65: subject_alt_name << 'DNS:' + name
66: subject_alt_name << 'DNS:' + name.sub(/^[^.]+./, "puppet.")
67: end
68: key_usage = %w{digitalSignature keyEncipherment}
69: ext_key_usage = %w{serverAuth clientAuth emailProtection}
70: when :ocsp
71: basic_constraint = "CA:FALSE"
72: key_usage = %w{nonRepudiation digitalSignature}
73: ext_key_usage = %w{serverAuth OCSPSigning}
74: when :client
75: basic_constraint = "CA:FALSE"
76: key_usage = %w{nonRepudiation digitalSignature keyEncipherment}
77: ext_key_usage = %w{clientAuth emailProtection}
78: ex << ef.create_extension("nsCertType", "client,email")
79: else
80: raise Puppet::Error, "unknown cert type '#{hash[:type]}'"
81: end
82:
83:
84: ex << ef.create_extension(
85: "nsComment",
86:
87: "Puppet Ruby/OpenSSL Generated Certificate")
88: ex << ef.create_extension("basicConstraints", basic_constraint, true)
89: ex << ef.create_extension("subjectKeyIdentifier", "hash")
90:
91: ex << ef.create_extension("keyUsage", key_usage.join(",")) if key_usage
92: ex << ef.create_extension("extendedKeyUsage", ext_key_usage.join(",")) if ext_key_usage
93: ex << ef.create_extension("subjectAltName", subject_alt_name.join(",")) if ! subject_alt_name.empty?
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104: cert.extensions = ex
105:
106:
107: ex << ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always") if hash[:type] == :ca
108:
109: cert
110: end