class Puppet::SSL::StateMachine
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.
@api private
Attributes
Public Class Methods
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.
@param waitforcert [Integer] how many seconds to wait between attempts @param maxwaitforcert [Integer] maximum amount of seconds to wait for the
server to sign the certificate request
@param waitforlock [Integer] how many seconds to wait between attempts for
acquiring the ssl lock
@param maxwaitforlock [Integer] maximum amount of seconds to wait for an
already running process to release the ssl lock
@param onetime [Boolean] whether to run onetime @param lockfile [Puppet::Util::Pidlock] lockfile to protect against
concurrent modification by multiple processes
@param cert_provider
[Puppet::X509::CertProvider] cert provider to use
to load and save X509 objects.
@param ssl_provider
[Puppet::SSL::SSLProvider] ssl provider to use
to construct ssl contexts.
@param digest [String] digest algorithm to use for certificate fingerprinting @param ca_fingerprint
[String] optional fingerprint to verify the
downloaded CA bundle
# File lib/puppet/ssl/state_machine.rb 381 def initialize(waitforcert: Puppet[:waitforcert], 382 maxwaitforcert: Puppet[:maxwaitforcert], 383 waitforlock: Puppet[:waitforlock], 384 maxwaitforlock: Puppet[:maxwaitforlock], 385 onetime: Puppet[:onetime], 386 cert_provider: Puppet::X509::CertProvider.new, 387 ssl_provider: Puppet::SSL::SSLProvider.new, 388 lockfile: Puppet::Util::Pidlock.new(Puppet[:ssl_lockfile]), 389 digest: 'SHA256', 390 ca_fingerprint: Puppet[:ca_fingerprint]) 391 @waitforcert = waitforcert 392 @wait_deadline = Time.now.to_i + maxwaitforcert 393 @waitforlock = waitforlock 394 @waitlock_deadline = Time.now.to_i + maxwaitforlock 395 @onetime = onetime 396 @cert_provider = cert_provider 397 @ssl_provider = ssl_provider 398 @lockfile = lockfile 399 @digest = digest 400 @ca_fingerprint = ca_fingerprint 401 @session = Puppet.runtime[:http].create_session 402 end
Public Instance Methods
Run the state machine for CA certs and CRLs.
@return [Puppet::SSL::SSLContext] initialized SSLContext @raise [Puppet::Error] If we fail to generate an SSLContext @api private
# File lib/puppet/ssl/state_machine.rb 409 def ensure_ca_certificates 410 final_state = run_machine(NeedLock.new(self), NeedKey) 411 final_state.ssl_context 412 end
Run the state machine for CA certs and CRLs.
@return [Puppet::SSL::SSLContext] initialized SSLContext @raise [Puppet::Error] If we fail to generate an SSLContext @api private
# File lib/puppet/ssl/state_machine.rb 419 def ensure_client_certificate 420 final_state = run_machine(NeedLock.new(self), Done) 421 ssl_context = final_state.ssl_context 422 423 if Puppet::Util::Log.sendlevel?(:debug) 424 chain = ssl_context.client_chain 425 # print from root to client 426 chain.reverse.each_with_index do |cert, i| 427 digest = Puppet::SSL::Digest.new(@digest, cert.to_der) 428 if i == chain.length - 1 429 Puppet.debug(_("Verified client certificate '%{subject}' fingerprint %{digest}") % {subject: cert.subject.to_utf8, digest: digest}) 430 else 431 Puppet.debug(_("Verified CA certificate '%{subject}' fingerprint %{digest}") % {subject: cert.subject.to_utf8, digest: digest}) 432 end 433 end 434 end 435 436 ssl_context 437 end
# File lib/puppet/ssl/state_machine.rb 439 def lock 440 @lockfile.lock 441 end
# File lib/puppet/ssl/state_machine.rb 443 def unlock 444 @lockfile.unlock 445 end
Private Instance Methods
# File lib/puppet/ssl/state_machine.rb 449 def run_machine(state, stop) 450 loop do 451 state = run_step(state) 452 453 case state 454 when stop 455 break 456 when LockFailure 457 raise Puppet::Error, state.message 458 when Error 459 if @onetime 460 Puppet.log_exception(state.error) 461 raise state.error 462 end 463 else 464 # fall through 465 end 466 end 467 468 state 469 ensure 470 @lockfile.unlock if @lockfile.locked? 471 end
# File lib/puppet/ssl/state_machine.rb 473 def run_step(state) 474 state.next_state 475 rescue => e 476 state.to_error(e.message, e) 477 end