@@ -556,12 +556,28 @@ func (cfg *Config) obtainOnDemandCertificate(ctx context.Context, hello *tls.Cli
556
556
//
557
557
// This function is safe for use by multiple concurrent goroutines.
558
558
func (cfg * Config ) handshakeMaintenance (ctx context.Context , hello * tls.ClientHelloInfo , cert Certificate ) (Certificate , error ) {
559
- logger := cfg .Logger .Named ("on_demand" )
559
+ logger := cfg .Logger .Named ("on_demand" ).With (
560
+ zap .Strings ("identifiers" , cert .Names ),
561
+ zap .String ("server_name" , hello .ServerName ))
562
+
563
+ renewIfNecessary := func (ctx context.Context , hello * tls.ClientHelloInfo , cert Certificate ) (Certificate , error ) {
564
+ if cfg .certNeedsRenewal (cert .Leaf , cert .ari , true ) {
565
+ // Check if the certificate still exists on disk. If not, we need to obtain a new one.
566
+ // This can happen if the certificate was cleaned up by the storage cleaner, but still
567
+ // remains in the in-memory cache.
568
+ if ! cfg .storageHasCertResourcesAnyIssuer (ctx , cert .Names [0 ]) {
569
+ logger .Debug ("certificate not found on disk; obtaining new certificate" )
570
+ return cfg .obtainOnDemandCertificate (ctx , hello )
571
+ }
572
+ // Otherwise, renew the certificate.
573
+ return cfg .renewDynamicCertificate (ctx , hello , cert )
574
+ }
575
+ return cert , nil
576
+ }
560
577
561
578
// Check OCSP staple validity
562
579
if cert .ocsp != nil && ! freshOCSP (cert .ocsp ) {
563
580
logger .Debug ("OCSP response needs refreshing" ,
564
- zap .Strings ("identifiers" , cert .Names ),
565
581
zap .Int ("ocsp_status" , cert .ocsp .Status ),
566
582
zap .Time ("this_update" , cert .ocsp .ThisUpdate ),
567
583
zap .Time ("next_update" , cert .ocsp .NextUpdate ))
@@ -570,13 +586,9 @@ func (cfg *Config) handshakeMaintenance(ctx context.Context, hello *tls.ClientHe
570
586
if err != nil {
571
587
// An error with OCSP stapling is not the end of the world, and in fact, is
572
588
// quite common considering not all certs have issuer URLs that support it.
573
- logger .Warn ("stapling OCSP" ,
574
- zap .String ("server_name" , hello .ServerName ),
575
- zap .Strings ("sans" , cert .Names ),
576
- zap .Error (err ))
589
+ logger .Warn ("stapling OCSP" , zap .Error (err ))
577
590
} else {
578
591
logger .Debug ("successfully stapled new OCSP response" ,
579
- zap .Strings ("identifiers" , cert .Names ),
580
592
zap .Int ("ocsp_status" , cert .ocsp .Status ),
581
593
zap .Time ("this_update" , cert .ocsp .ThisUpdate ),
582
594
zap .Time ("next_update" , cert .ocsp .NextUpdate ))
@@ -590,41 +602,37 @@ func (cfg *Config) handshakeMaintenance(ctx context.Context, hello *tls.ClientHe
590
602
591
603
// Check ARI status
592
604
if ! cfg .DisableARI && cert .ari .NeedsRefresh () {
593
- // we ignore the second return value here because we go on to check renewal status below regardless
594
- var err error
595
- cert , _ , err = cfg .updateARI (ctx , cert , logger )
596
- if err != nil {
597
- logger .Error ("updated ARI" , zap .Error (err ))
598
- }
605
+ // update ARI in a goroutine to avoid blocking an active handshake, since the results of
606
+ // this do not strictly affect the handshake; even though the cert may be updated with
607
+ // the new ARI, it is also updated in the cache and in storage, so future handshakes
608
+ // will utilize it
609
+ go func (ctx context.Context , hello * tls.ClientHelloInfo , cert Certificate , logger * zap.Logger ) {
610
+ var err error
611
+ // we ignore the second return value here because we check renewal status below regardless
612
+ cert , _ , err = cfg .updateARI (ctx , cert , logger )
613
+ if err != nil {
614
+ logger .Error ("updating ARI" , zap .Error (err ))
615
+ }
616
+ _ , err = renewIfNecessary (ctx , hello , cert )
617
+ if err != nil {
618
+ logger .Error ("renewing certificate based on updated ARI" , zap .Error (err ))
619
+ }
620
+ }(ctx , hello , cert , logger )
599
621
}
600
622
601
623
// We attempt to replace any certificates that were revoked.
602
624
// Crucially, this happens OUTSIDE a lock on the certCache.
603
625
if certShouldBeForceRenewed (cert ) {
604
626
logger .Warn ("on-demand certificate's OCSP status is REVOKED; will try to forcefully renew" ,
605
- zap .Strings ("identifiers" , cert .Names ),
606
627
zap .Int ("ocsp_status" , cert .ocsp .Status ),
607
628
zap .Time ("revoked_at" , cert .ocsp .RevokedAt ),
608
629
zap .Time ("this_update" , cert .ocsp .ThisUpdate ),
609
630
zap .Time ("next_update" , cert .ocsp .NextUpdate ))
610
631
return cfg .renewDynamicCertificate (ctx , hello , cert )
611
632
}
612
633
613
- // Check cert expiration
614
- if cfg .certNeedsRenewal (cert .Leaf , cert .ari , true ) {
615
- // Check if the certificate still exists on disk. If not, we need to obtain a new one.
616
- // This can happen if the certificate was cleaned up by the storage cleaner, but still
617
- // remains in the in-memory cache.
618
- if ! cfg .storageHasCertResourcesAnyIssuer (ctx , cert .Names [0 ]) {
619
- logger .Debug ("certificate not found on disk; obtaining new certificate" ,
620
- zap .Strings ("identifiers" , cert .Names ))
621
- return cfg .obtainOnDemandCertificate (ctx , hello )
622
- }
623
- // Otherwise, renew the certificate.
624
- return cfg .renewDynamicCertificate (ctx , hello , cert )
625
- }
626
-
627
- return cert , nil
634
+ // Since renewal conditions may have changed, do a renewal if necessary
635
+ return renewIfNecessary (ctx , hello , cert )
628
636
}
629
637
630
638
// renewDynamicCertificate renews the certificate for name using cfg. It returns the
0 commit comments