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, LockFailure, NeedCACerts, NeedCRLs, NeedCert, NeedKey, NeedLock, NeedSubmitCSR, SSLState, Wait

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#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]) ⇒ 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: Puppet[:waitforcert])

    how many seconds to wait between attempts

  • maxwiatforcert (Integer)

    maximum amount of second

  • onetime (Boolean) (defaults to: Puppet[:onetime])

    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: Puppet[:ca_fingerprint])

    optional fingerprint to verify the downloaded CA bundle


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

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
  @session = Puppet.runtime['http'].create_session
end

Instance Attribute Details

#ca_fingerprintObject (readonly)

Returns the value of attribute ca_fingerprint


336
337
338
# File 'lib/puppet/ssl/state_machine.rb', line 336

def ca_fingerprint
  @ca_fingerprint
end

#cert_providerObject (readonly)

Returns the value of attribute cert_provider


336
337
338
# File 'lib/puppet/ssl/state_machine.rb', line 336

def cert_provider
  @cert_provider
end

#digestObject (readonly)

Returns the value of attribute digest


336
337
338
# File 'lib/puppet/ssl/state_machine.rb', line 336

def digest
  @digest
end

#sessionObject

Returns the value of attribute session


337
338
339
# File 'lib/puppet/ssl/state_machine.rb', line 337

def session
  @session
end

#ssl_providerObject (readonly)

Returns the value of attribute ssl_provider


336
337
338
# File 'lib/puppet/ssl/state_machine.rb', line 336

def ssl_provider
  @ssl_provider
end

#wait_deadlineObject (readonly)

Returns the value of attribute wait_deadline


336
337
338
# File 'lib/puppet/ssl/state_machine.rb', line 336

def wait_deadline
  @wait_deadline
end

#waitforcertObject (readonly)

Returns the value of attribute waitforcert


336
337
338
# File 'lib/puppet/ssl/state_machine.rb', line 336

def waitforcert
  @waitforcert
end

Instance Method Details

#ensure_ca_certificatesPuppet::SSL::SSLContext

Run the state machine for CA certs and CRLs.

Returns:

Raises:


383
384
385
386
# File 'lib/puppet/ssl/state_machine.rb', line 383

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

#ensure_client_certificatePuppet::SSL::SSLContext

Run the state machine for CA certs and CRLs.

Returns:

Raises:


392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
# File 'lib/puppet/ssl/state_machine.rb', line 392

def ensure_client_certificate
  final_state = run_machine(NeedLock.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

#lockObject


412
413
414
# File 'lib/puppet/ssl/state_machine.rb', line 412

def lock
  @lockfile.lock
end

#unlockObject


416
417
418
# File 'lib/puppet/ssl/state_machine.rb', line 416

def unlock
  @lockfile.unlock
end