Skip to content

Commit 1d41169

Browse files
committed
(PUP-11869) Retry failed CA/CRL refreshes sooner
Prior to this commit, any time a node attempted to refresh its certificate authority (CA) or certificate revocation list (CRL), regardless of whether it was successful in doing so, Puppet would update the modified timestamp (mtime) on the CA or CRL file. Puppet uses the mtime to decide when to attempt to update a CA or CRL. As a result, if Puppet attempted but failed to updates either of those file, it would need to wait the full refresh interval before trying again. This commit changes Puppet to only update the modified timestamp on the CA or CRL files if they have been successfully refreshed. This means that if Puppet fails to update its CA or CRL, it will try again the next run interval instead of waiting for the full CA or CRL refresh interval (which should be greater than the run interval).
1 parent 28c58fb commit 1d41169

File tree

2 files changed

+21
-8
lines changed

2 files changed

+21
-8
lines changed

lib/puppet/ssl/state_machine.rb

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,6 @@ def next_state
5959
now = Time.now
6060
last_update = @cert_provider.ca_last_update
6161
if needs_refresh?(now, last_update)
62-
# set last updated time first, then make a best effort to refresh
63-
@cert_provider.ca_last_update = now
64-
6562
# If we refresh the CA, then we need to force the CRL to be refreshed too,
6663
# since if there is a new CA in the chain, then we need its CRL to check
6764
# the full chain for revocation status.
@@ -114,7 +111,12 @@ def refresh_ca(ssl_ctx, last_update)
114111
Puppet.info(_("Refreshing CA certificate"))
115112

116113
# return the next_ctx containing the updated ca
117-
[download_ca(ssl_ctx, last_update), true]
114+
next_ctx = [download_ca(ssl_ctx, last_update), true]
115+
116+
# After a successful refresh, update ca_last_update
117+
@cert_provider.ca_last_update = Time.now
118+
119+
next_ctx
118120
rescue Puppet::HTTP::ResponseError => e
119121
if e.response.code == 304
120122
Puppet.info(_("CA certificate is unmodified, using existing CA certificate"))
@@ -171,8 +173,6 @@ def next_state
171173
now = Time.now
172174
last_update = @cert_provider.crl_last_update
173175
if needs_refresh?(now, last_update)
174-
# set last updated time first, then make a best effort to refresh
175-
@cert_provider.crl_last_update = now
176176
next_ctx = refresh_crl(next_ctx, last_update)
177177
end
178178
else
@@ -209,7 +209,12 @@ def refresh_crl(ssl_ctx, last_update)
209209
Puppet.info(_("Refreshing CRL"))
210210

211211
# return the next_ctx containing the updated crl
212-
download_crl(ssl_ctx, last_update)
212+
next_ctx = download_crl(ssl_ctx, last_update)
213+
214+
# After a successful refresh, update crl_last_update
215+
@cert_provider.crl_last_update = Time.now
216+
217+
next_ctx
213218
rescue Puppet::HTTP::ResponseError => e
214219
if e.response.code == 304
215220
Puppet.info(_("CRL is unmodified, using existing CRL"))

spec/unit/ssl/state_machine_spec.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,14 +487,22 @@ def expect_lockfile_to_contain(pid)
487487
expect(state.next_state.ssl_context.cacerts.map(&:to_pem)).to eq(new_ca_bundle)
488488
end
489489

490-
it 'updates the `last_update` time' do
490+
it 'updates the `last_update` time on successful CA refresh' do
491491
stub_request(:get, %r{puppet-ca/v1/certificate/ca}).to_return(status: 200, body: new_ca_bundle.join)
492492

493493
expect_any_instance_of(Puppet::X509::CertProvider).to receive(:ca_last_update=).with(be_within(60).of(Time.now))
494494

495495
state.next_state
496496
end
497497

498+
it "does not update the `last_update` time when CA refresh fails" do
499+
stub_request(:get, %r{puppet-ca/v1/certificate/ca}).to_raise(Errno::ECONNREFUSED)
500+
501+
expect_any_instance_of(Puppet::X509::CertProvider).to receive(:ca_last_update=).never
502+
503+
state.next_state
504+
end
505+
498506
it 'forces the NeedCRLs to refresh' do
499507
stub_request(:get, %r{puppet-ca/v1/certificate/ca}).to_return(status: 200, body: new_ca_bundle.join)
500508

0 commit comments

Comments
 (0)