Class: Puppet::SSL::StateMachine

Inherits:
Object
  • Object
show all
Defined in:
lib/puppet/ssl/state_machine.rb

Overview

This class implements a state machine for bootstrapping a host's CA and CRL bundles, private key and signed client certificate. Each state has a frozen SSLContext that it uses to make network connections. If a state makes progress bootstrapping the host, then the state will generate a new frozen SSLContext and pass that to the next state. For example, the NeedCACerts state will load or download a CA bundle, and generate a new SSLContext containing those CA certs. This way we're sure about which SSLContext is being used during any phase of the bootstrapping process.

Defined Under Namespace

Classes: Done, Error, KeySSLState, NeedCACerts, NeedCRLs, NeedCert, NeedKey, NeedSubmitCSR, SSLState, Wait

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(waitforcert: , maxwaitforcert: , onetime: , cert_provider: Puppet::X509::CertProvider.new, ssl_provider: Puppet::SSL::SSLProvider.new, lockfile: Puppet::Util::Pidlock.new(Puppet[:ssl_lockfile]), digest: 'SHA256', ca_fingerprint: ) ⇒ StateMachine

Construct a state machine to manage the SSL initialization process. By default, if the state machine encounters an exception, it will log the exception and wait for waitforcert seconds and retry, restarting from the beginning of the state machine.

However, if onetime is true, then the state machine will raise the first error it encounters, instead of waiting. Otherwise, if waitforcert is 0, then then state machine will exit instead of wait.

Parameters:

  • waitforcert (Integer) (defaults to: ) —

    how many seconds to wait between attempts

  • maxwiatforcert (Integer) —

    maximum amount of second

  • onetime (Boolean) (defaults to: ) —

    whether to run onetime

  • lockfile (Puppet::Util::Pidlock) (defaults to: Puppet::Util::Pidlock.new(Puppet[:ssl_lockfile])) —

    lockfile to protect against concurrent modification by multiple processes

  • cert_provider (Puppet::X509::CertProvider) (defaults to: Puppet::X509::CertProvider.new) —

    cert provider to use to load and save X509 objects.

  • ssl_provider (Puppet::SSL::SSLProvider) (defaults to: Puppet::SSL::SSLProvider.new) —

    ssl provider to use to construct ssl contexts.

  • digest (String) (defaults to: 'SHA256') —

    digest algorithm to use for certificate fingerprinting

  • ca_fingerprint (String) (defaults to: ) —

    optional fingerprint to verify the downloaded CA bundle



330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/puppet/ssl/state_machine.rb', line 330

def initialize(waitforcert: Puppet[:waitforcert],
               maxwaitforcert: Puppet[:maxwaitforcert],
               onetime: Puppet[:onetime],
               cert_provider: Puppet::X509::CertProvider.new,
               ssl_provider: Puppet::SSL::SSLProvider.new,
               lockfile: Puppet::Util::Pidlock.new(Puppet[:ssl_lockfile]),
               digest: 'SHA256',
               ca_fingerprint: Puppet[:ca_fingerprint])
  @waitforcert = waitforcert
  @wait_deadline = Time.now.to_i + maxwaitforcert
  @onetime = onetime
  @cert_provider = cert_provider
  @ssl_provider = ssl_provider
  @lockfile = lockfile
  @digest = digest
  @ca_fingerprint = ca_fingerprint
end

Instance Attribute Details

#ca_fingerprint ⇒ Object (readonly)

Returns the value of attribute ca_fingerprint.



307
308
309
# File 'lib/puppet/ssl/state_machine.rb', line 307

def ca_fingerprint
  @ca_fingerprint
end

#cert_provider ⇒ Object (readonly)

Returns the value of attribute cert_provider.



307
308
309
# File 'lib/puppet/ssl/state_machine.rb', line 307

def cert_provider
  @cert_provider
end

#digest ⇒ Object (readonly)

Returns the value of attribute digest.



307
308
309
# File 'lib/puppet/ssl/state_machine.rb', line 307

def digest
  @digest
end

#ssl_provider ⇒ Object (readonly)

Returns the value of attribute ssl_provider.



307
308
309
# File 'lib/puppet/ssl/state_machine.rb', line 307

def ssl_provider
  @ssl_provider
end

#wait_deadline ⇒ Object (readonly)

Returns the value of attribute wait_deadline.



307
308
309
# File 'lib/puppet/ssl/state_machine.rb', line 307

def wait_deadline
  @wait_deadline
end

#waitforcert ⇒ Object (readonly)

Returns the value of attribute waitforcert.



307
308
309
# File 'lib/puppet/ssl/state_machine.rb', line 307

def waitforcert
  @waitforcert
end

Instance Method Details

#ensure_ca_certificates ⇒ Puppet::SSL::SSLContext

Run the state machine for CA certs and CRLs.

Returns:

Raises:



352
353
354
355
# File 'lib/puppet/ssl/state_machine.rb', line 352

def ensure_ca_certificates
  final_state = run_machine(NeedCACerts.new(self), NeedKey)
  final_state.ssl_context
end

#ensure_client_certificate ⇒ Puppet::SSL::SSLContext

Run the state machine for CA certs and CRLs.

Returns:

Raises:



361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
# File 'lib/puppet/ssl/state_machine.rb', line 361

def ensure_client_certificate
  final_state = run_machine(NeedCACerts.new(self), Done)
  ssl_context = final_state.ssl_context

  if Puppet::Util::Log.sendlevel?(:debug)
    chain = ssl_context.client_chain
    # print from root to client
    chain.reverse.each_with_index do |cert, i|
      digest = Puppet::SSL::Digest.new(@digest, cert.to_der)
      if i == chain.length - 1
        Puppet.debug(_("Verified client certificate '%{subject}' fingerprint %{digest}") % {subject: cert.subject.to_utf8, digest: digest})
      else
        Puppet.debug(_("Verified CA certificate '%{subject}' fingerprint %{digest}") % {subject: cert.subject.to_utf8, digest: digest})
      end
    end
  end

  ssl_context
end