Class: Puppetserver::Ca::LocalCertificateAuthority
- Inherits:
-
Object
- Object
- Puppetserver::Ca::LocalCertificateAuthority
- Defined in:
- lib/puppetserver/ca/local_certificate_authority.rb
Constant Summary collapse
- CERT_VALID_FROM =
Make the certificate valid as of yesterday, because so many people’s clocks are out of sync. This gives one more day of validity than people might expect, but is better than making every person who has a messed up clock fail, and better than having every cert we generate expire a day before the user expected it to when they asked for “one year”.
(Time.now - (60*60*24)).freeze
- SSL_SERVER_CERT =
"1.3.6.1.5.5.7.3.1"
- SSL_CLIENT_CERT =
"1.3.6.1.5.5.7.3.2"
- CLI_AUTH_EXT_OID =
"1.3.6.1.4.1.34380.1.3.39"
- MASTER_EXTENSIONS =
[ ["basicConstraints", "CA:FALSE", true], ["nsComment", "Puppet Server Internal Certificate", false], ["authorityKeyIdentifier", "keyid:always", false], ["extendedKeyUsage", "#{SSL_SERVER_CERT}, #{SSL_CLIENT_CERT}", true], ["keyUsage", "keyEncipherment, digitalSignature", true], ["subjectKeyIdentifier", "hash", false] ].freeze
- CA_EXTENSIONS =
[ ["basicConstraints", "CA:TRUE", true], ["keyUsage", "keyCertSign, cRLSign", true], ["subjectKeyIdentifier", "hash", false], ["nsComment", "Puppet Server Internal Certificate", false], ["authorityKeyIdentifier", "keyid:always", false] ].freeze
Instance Attribute Summary collapse
-
#cert ⇒ Object
readonly
Returns the value of attribute cert.
-
#cert_bundle ⇒ Object
readonly
Returns the value of attribute cert_bundle.
-
#crl ⇒ Object
readonly
Returns the value of attribute crl.
-
#crl_chain ⇒ Object
readonly
Returns the value of attribute crl_chain.
-
#key ⇒ Object
readonly
Returns the value of attribute key.
Instance Method Summary collapse
- #add_authorized_extensions(cert, ef) ⇒ Object
-
#add_custom_extensions(cert) ⇒ Object
This takes all the extension requests from csr_attributes.yaml and adds those to the cert.
- #add_subject_alt_names_extension(alt_names, cert, ef) ⇒ Object
- #create_crl_for(cert, key) ⇒ Object
- #create_intermediate_cert(root_key, root_cert) ⇒ Object
- #create_master_cert ⇒ Object
- #create_root_cert ⇒ Object
- #errors ⇒ Object
- #extension_factory_for(ca, cert = nil) ⇒ Object
- #format_time(time) ⇒ Object
-
#initialize(digest, settings) ⇒ LocalCertificateAuthority
constructor
A new instance of LocalCertificateAuthority.
-
#initialize_ssl_components(loader) ⇒ void
Initialize SSL state.
- #inventory_entry(cert) ⇒ Object
- #load_ssl_components(loader) ⇒ Object
- #next_serial(serial_file) ⇒ Object
- #self_signed_ca(key) ⇒ Object
- #sign_authorized_cert(csr, alt_names = '') ⇒ Object
- #sign_intermediate(ca_key, ca_cert, csr) ⇒ Object
- #ssl_assets_exist? ⇒ Boolean
- #update_serial_file(serial) ⇒ Object
- #valid_until ⇒ Object
Constructor Details
#initialize(digest, settings) ⇒ LocalCertificateAuthority
Returns a new instance of LocalCertificateAuthority.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 42 def initialize(digest, settings) @digest = digest @host = Host.new(digest) @settings = settings @errors = [] if ssl_assets_exist? loader = Puppetserver::Ca::X509Loader.new(@settings[:cacert], @settings[:cakey], @settings[:cacrl]) if loader.errors.empty? load_ssl_components(loader) else @errors += loader.errors @errors << "CA not initialized. Please set up your CA before attempting to generate certs offline." end end end |
Instance Attribute Details
#cert ⇒ Object (readonly)
Returns the value of attribute cert.
40 41 42 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 40 def cert @cert end |
#cert_bundle ⇒ Object (readonly)
Returns the value of attribute cert_bundle.
40 41 42 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 40 def cert_bundle @cert_bundle end |
#crl ⇒ Object (readonly)
Returns the value of attribute crl.
40 41 42 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 40 def crl @crl end |
#crl_chain ⇒ Object (readonly)
Returns the value of attribute crl_chain.
40 41 42 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 40 def crl_chain @crl_chain end |
#key ⇒ Object (readonly)
Returns the value of attribute key.
40 41 42 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 40 def key @key end |
Instance Method Details
#add_authorized_extensions(cert, ef) ⇒ Object
178 179 180 181 182 183 184 185 186 187 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 178 def (cert, ef) MASTER_EXTENSIONS.each do |ext| extension = ef.create_extension(*ext) cert.add_extension(extension) end # Status API access for the CA CLI cli_auth_ext = OpenSSL::X509::Extension.new(CLI_AUTH_EXT_OID, OpenSSL::ASN1::UTF8String.new("true").to_der, false) cert.add_extension(cli_auth_ext) end |
#add_custom_extensions(cert) ⇒ Object
This takes all the extension requests from csr_attributes.yaml and adds those to the cert
196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 196 def add_custom_extensions(cert) extension_requests = @host.get_extension_requests(@settings[:csr_attributes]) if extension_requests extensions = @host.validated_extensions(extension_requests) extensions.each do |ext| cert.add_extension(ext) end end @host.errors.empty? end |
#add_subject_alt_names_extension(alt_names, cert, ef) ⇒ Object
189 190 191 192 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 189 def add_subject_alt_names_extension(alt_names, cert, ef) alt_names_ext = ef.create_extension("subjectAltName", alt_names, false) cert.add_extension(alt_names_ext) end |
#create_crl_for(cert, key) ⇒ Object
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 240 def create_crl_for(cert, key) crl = OpenSSL::X509::CRL.new crl.version = 1 crl.issuer = cert.subject ef = extension_factory_for(cert) crl.add_extension( ef.create_extension(["authorityKeyIdentifier", "keyid:always", false])) crl.add_extension( OpenSSL::X509::Extension.new("crlNumber", OpenSSL::ASN1::Integer(0))) crl.last_update = CERT_VALID_FROM crl.next_update = valid_until crl.sign(key, @digest) crl end |
#create_intermediate_cert(root_key, root_cert) ⇒ Object
258 259 260 261 262 263 264 265 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 258 def create_intermediate_cert(root_key, root_cert) @key = @host.create_private_key(@settings[:keylength]) int_csr = @host.create_csr(name: @settings[:ca_name], key: @key) @cert = sign_intermediate(root_key, root_cert, int_csr) @crl = create_crl_for(@cert, @key) return nil end |
#create_master_cert ⇒ Object
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 135 def create_master_cert master_cert = nil master_key = @host.create_private_key(@settings[:keylength], @settings[:hostprivkey], @settings[:hostpubkey]) if master_key master_csr = @host.create_csr(name: @settings[:certname], key: master_key) if @settings[:subject_alt_names].empty? alt_names = "DNS:puppet, DNS:#{@settings[:certname]}" else alt_names = @settings[:subject_alt_names] end master_cert = (master_csr, alt_names) end return master_key, master_cert end |
#create_root_cert ⇒ Object
209 210 211 212 213 214 215 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 209 def create_root_cert root_key = @host.create_private_key(@settings[:keylength]) root_cert = self_signed_ca(root_key) root_crl = create_crl_for(root_cert, root_key) return root_key, root_cert, root_crl end |
#errors ⇒ Object
102 103 104 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 102 def errors @errors += @host.errors end |
#extension_factory_for(ca, cert = nil) ⇒ Object
110 111 112 113 114 115 116 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 110 def extension_factory_for(ca, cert = nil) ef = OpenSSL::X509::ExtensionFactory.new ef.issuer_certificate = ca ef.subject_certificate = cert if cert ef end |
#format_time(time) ⇒ Object
131 132 133 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 131 def format_time(time) time.strftime('%Y-%m-%dT%H:%M:%S%Z') end |
#initialize_ssl_components(loader) ⇒ void
Check #errors after calling this method for issues that may have occurred during initialization.
This method returns an undefined value.
Initialize SSL state
This method is similar to #load_ssl_components, but has extra logic for initializing components that may not be present when the CA is set up for the first time. For example, SSL components provided by an external CA will often not include a pre-generated leaf CRL.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 86 def initialize_ssl_components(loader) @cert_bundle = loader.certs @key = loader.key @cert = loader.cert if loader.crl.nil? loader.crl = create_crl_for(@cert, @key) loader.validate_full_chain(@cert_bundle, loader.crls) @errors += loader.errors end @crl_chain = loader.crls @crl = loader.crl end |
#inventory_entry(cert) ⇒ Object
118 119 120 121 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 118 def inventory_entry(cert) "0x%04x %s %s %s" % [cert.serial, format_time(cert.not_before), format_time(cert.not_after), cert.subject] end |
#load_ssl_components(loader) ⇒ Object
65 66 67 68 69 70 71 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 65 def load_ssl_components(loader) @cert_bundle = loader.certs @key = loader.key @cert = loader.cert @crl_chain = loader.crls @crl = loader.crl end |
#next_serial(serial_file) ⇒ Object
123 124 125 126 127 128 129 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 123 def next_serial(serial_file) if File.exist?(serial_file) File.read(serial_file).to_i(16) else 1 end end |
#self_signed_ca(key) ⇒ Object
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 217 def self_signed_ca(key) cert = OpenSSL::X509::Certificate.new cert.public_key = key.public_key cert.subject = OpenSSL::X509::Name.new([["CN", @settings[:root_ca_name]]]) cert.issuer = cert.subject cert.version = 2 cert.serial = 1 cert.not_before = CERT_VALID_FROM cert.not_after = valid_until ef = extension_factory_for(cert, cert) CA_EXTENSIONS.each do |ext| extension = ef.create_extension(*ext) cert.add_extension(extension) end cert.sign(key, @digest) cert end |
#sign_authorized_cert(csr, alt_names = '') ⇒ Object
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 154 def (csr, alt_names = '') cert = OpenSSL::X509::Certificate.new cert.public_key = csr.public_key cert.subject = csr.subject cert.issuer = @cert.subject cert.version = 2 cert.serial = next_serial(@settings[:serial]) cert.not_before = CERT_VALID_FROM cert.not_after = valid_until return unless add_custom_extensions(cert) ef = extension_factory_for(@cert, cert) (cert, ef) if !alt_names.empty? add_subject_alt_names_extension(alt_names, cert, ef) end cert.sign(@key, @digest) cert end |
#sign_intermediate(ca_key, ca_cert, csr) ⇒ Object
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 267 def sign_intermediate(ca_key, ca_cert, csr) cert = OpenSSL::X509::Certificate.new cert.public_key = csr.public_key cert.subject = csr.subject cert.issuer = ca_cert.subject cert.version = 2 cert.serial = 2 cert.not_before = CERT_VALID_FROM cert.not_after = valid_until ef = extension_factory_for(ca_cert, cert) CA_EXTENSIONS.each do |ext| extension = ef.create_extension(*ext) cert.add_extension(extension) end cert.sign(ca_key, @digest) cert end |
#ssl_assets_exist? ⇒ Boolean
59 60 61 62 63 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 59 def ssl_assets_exist? File.exist?(@settings[:cacert]) && File.exist?(@settings[:cakey]) && File.exist?(@settings[:cacrl]) end |
#update_serial_file(serial) ⇒ Object
290 291 292 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 290 def update_serial_file(serial) Puppetserver::Ca::Utils::FileSystem.write_file(@settings[:serial], serial.to_s(16), 0644) end |
#valid_until ⇒ Object
106 107 108 |
# File 'lib/puppetserver/ca/local_certificate_authority.rb', line 106 def valid_until Time.now + @settings[:ca_ttl] end |