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
|
# 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, 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
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"
key_usage = %w{digitalSignature keyEncipherment}
ext_key_usage = %w{serverAuth clientAuth}
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")
if key_usage
ex << ef.create_extension("keyUsage", key_usage.join(","))
end
if ext_key_usage
ex << ef.create_extension("extendedKeyUsage", ext_key_usage.join(","))
end
#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
if hash[:type] == :ca
ex << ef.create_extension("authorityKeyIdentifier",
"keyid:always,issuer:always")
end
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
# $Id$
|