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], waitforlock: Puppet[:waitforlock], maxwaitforlock: Puppet[:maxwaitforlock], 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

  • maxwaitforcert (Integer) (defaults to: Puppet[:maxwaitforcert])

    maximum amount of seconds to wait for the server to sign the certificate request

  • waitforlock (Integer) (defaults to: Puppet[:waitforlock])

    how many seconds to wait between attempts for acquiring the ssl lock

  • maxwaitforlock (Integer) (defaults to: Puppet[:maxwaitforlock])

    maximum amount of seconds to wait for an already running process to release the ssl lock

  • 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


381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/puppet/ssl/state_machine.rb', line 381

def initialize(waitforcert: Puppet[:waitforcert],
               maxwaitforcert: Puppet[:maxwaitforcert],
               waitforlock: Puppet[:waitforlock],
               maxwaitforlock: Puppet[:maxwaitforlock],
               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
  @waitforlock = waitforlock
  @waitlock_deadline = Time.now.to_i + maxwaitforlock
  @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


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

def ca_fingerprint
  @ca_fingerprint
end

#cert_providerObject (readonly)

Returns the value of attribute cert_provider


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

def cert_provider
  @cert_provider
end

#digestObject (readonly)

Returns the value of attribute digest


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

def digest
  @digest
end

#sessionObject

Returns the value of attribute session


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

def session
  @session
end

#ssl_providerObject (readonly)

Returns the value of attribute ssl_provider


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

def ssl_provider
  @ssl_provider
end

#wait_deadlineObject (readonly)

Returns the value of attribute wait_deadline


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

def wait_deadline
  @wait_deadline
end

#waitforcertObject (readonly)

Returns the value of attribute waitforcert


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

def waitforcert
  @waitforcert
end

#waitforlockObject (readonly)

Returns the value of attribute waitforlock


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

def waitforlock
  @waitforlock
end

#waitlock_deadlineObject (readonly)

Returns the value of attribute waitlock_deadline


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

def waitlock_deadline
  @waitlock_deadline
end

Instance Method Details

#ensure_ca_certificatesPuppet::SSL::SSLContext

Run the state machine for CA certs and CRLs.

Returns:

Raises:


408
409
410
411
# File 'lib/puppet/ssl/state_machine.rb', line 408

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:


417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
# File 'lib/puppet/ssl/state_machine.rb', line 417

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


437
438
439
# File 'lib/puppet/ssl/state_machine.rb', line 437

def lock
  @lockfile.lock
end

#unlockObject


441
442
443
# File 'lib/puppet/ssl/state_machine.rb', line 441

def unlock
  @lockfile.unlock
end