1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
# The library for manipulating SSL certs.
require 'puppet'
begin
require 'openssl'
rescue LoadError
raise Puppet::Error, "You must have the Ruby openssl library installed"
end
module Puppet::SSLCertificates
#def self.mkcert(type, name, dnsnames, ttl, issuercert, issuername, serial, publickey)
def self.mkcert(hash)
[:type, :name, :ttl, :issuer, :serial, :publickey].each { |param|
unless hash.include?(param)
raise ArgumentError, "mkcert called without %s" % param
end
}
cert = OpenSSL::X509::Certificate.new
# Make the certificate valid as of yesterday, because
# so many people's clocks are out of sync.
from = Time.now - (60*60*24)
cert.subject = hash[:name]
if hash[:issuer]
cert.issuer = hash[:issuer].subject
else
# we're a self-signed cert
cert.issuer = hash[:name]
end
cert.not_before = from
cert.not_after = from + hash[:ttl]
cert.version = 2 # X509v3
cert.public_key = hash[:publickey]
cert.serial = hash[:serial]
basic_constraint = nil
key_usage = nil
ext_key_usage = nil
subject_alt_name = []
ef = OpenSSL::X509::ExtensionFactory.new
ef.subject_certificate = cert
if hash[:issuer]
ef.issuer_certificate = hash[:issuer]
else
ef.issuer_certificate = cert
end
ex = []
case hash[:type]
when :ca
basic_constraint = "CA:TRUE"
key_usage = %w{cRLSign keyCertSign}
when :terminalsubca
basic_constraint = "CA:TRUE,pathlen:0"
key_usage = %w{cRLSign keyCertSign}
when :server
basic_constraint = "CA:FALSE"
dnsnames = Puppet[:certdnsnames]
name = hash[:name].to_s.sub(%r{/CN=},'')
if dnsnames != ""
dnsnames.split(':').each { |d| subject_alt_name << 'DNS:' + d }
subject_alt_name << 'DNS:' + name # Add the fqdn as an alias
elsif name == Facter.value(:fqdn) # we're a CA server, and thus probably the server
subject_alt_name << 'DNS:' + "puppet" # Add 'puppet' as an alias
subject_alt_name << 'DNS:' + name # Add the fqdn as an alias
subject_alt_name << 'DNS:' + name.sub(/^[^.]+./, "puppet.") # add puppet.domain as an alias
end
key_usage = %w{digitalSignature keyEncipherment}
ext_key_usage = %w{serverAuth clientAuth emailProtection}
when :ocsp
basic_constraint = "CA:FALSE"
key_usage = %w{nonRepudiation digitalSignature}
ext_key_usage = %w{serverAuth OCSPSigning}
when :client
basic_constraint = "CA:FALSE"
key_usage = %w{nonRepudiation digitalSignature keyEncipherment}
ext_key_usage = %w{clientAuth emailProtection}
ex << ef.create_extension("nsCertType", "client,email")
else
raise Puppet::Error, "unknown cert type '%s'" % hash[:type]
end
ex << ef.create_extension("nsComment",
"Puppet Ruby/OpenSSL Generated Certificate")
ex << ef.create_extension("basicConstraints", basic_constraint, true)
ex << ef.create_extension("subjectKeyIdentifier", "hash")
ex << ef.create_extension("keyUsage", key_usage.join(",")) if key_usage
ex << ef.create_extension("extendedKeyUsage", ext_key_usage.join(",")) if ext_key_usage
ex << ef.create_extension("subjectAltName", subject_alt_name.join(",")) if ! subject_alt_name.empty?
#if @ca_config[:cdp_location] then
# ex << ef.create_extension("crlDistributionPoints",
# @ca_config[:cdp_location])
#end
#if @ca_config[:ocsp_location] then
# ex << ef.create_extension("authorityInfoAccess",
# "OCSP;" << @ca_config[:ocsp_location])
#end
cert.extensions = ex
# for some reason this _must_ be the last extension added
ex << ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always") if hash[:type] == :ca
return cert
end
def self.mkhash(dir, cert, certfile)
# Make sure the hash is zero-padded to 8 chars
hash = "%08x" % cert.issuer.hash
hashpath = nil
10.times { |i|
path = File.join(dir, "%s.%s" % [hash, i])
if FileTest.exists?(path)
if FileTest.symlink?(path)
dest = File.readlink(path)
if dest == certfile
# the correct link already exists
hashpath = path
break
else
next
end
else
next
end
end
File.symlink(certfile, path)
hashpath = path
break
}
return hashpath
end
require 'puppet/sslcertificates/certificate'
require 'puppet/sslcertificates/inventory'
require 'puppet/sslcertificates/ca'
end
|