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 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
# 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
hostname = Facter["hostname"].value
domain = Facter["domain"].value
fqdn = [hostname, domain].join(".")
Puppet.setdefaults("certificates",
:certdir => ["$ssldir/certs", "The certificate directory."],
:publickeydir => ["$ssldir/public_keys", "The public key directory."],
:privatekeydir => { :default => "$ssldir/private_keys",
:mode => 0750,
:desc => "The private key directory."
},
:privatedir => { :default => "$ssldir/private",
:mode => 0750,
:desc => "Where the client stores private certificate information."
},
:passfile => { :default => "$privatedir/password",
:mode => 0640,
:desc => "Where puppetd stores the password for its private key.
Generally unused."
},
:hostcert => { :default => "$certdir/#{fqdn}.pem",
:mode => 0644,
:desc => "Where individual hosts store and look for their certificates."
},
:hostprivkey => { :default => "$privatekeydir/#{fqdn}.pem",
:mode => 0600,
:desc => "Where individual hosts store and look for their private key."
},
:hostpubkey => { :default => "$publickeydir/#{fqdn}.pem",
:mode => 0644,
:desc => "Where individual hosts store and look for their public key."
},
:localcacert => { :default => "$certdir/ca.pem",
:mode => 0644,
:desc => "Where each client stores the CA certificate."
}
)
#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
from = Time.now
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: sslcertificates.rb 1581 2006-09-13 16:50:43Z lutter $
|