@@ -375,6 +375,37 @@ func (cfg *Config) CacheUnmanagedCertificatePEMBytes(ctx context.Context, certBy
375375 return cert .hash , nil
376376}
377377
378+ // CacheUnmanagedCertificatePEMBytesAsReplacement is the same as CacheUnmanagedCertificatePEMBytes,
379+ // but it also removes any other loaded certificates for the SANs on the certificate being cached.
380+ // This has the effect of using this certificate exclusively and immediately for its SANs. The SANs
381+ // for which the certificate should apply may optionally be passed in as well. By default, a cert
382+ // is used for any of its SANs.
383+ //
384+ // This method is safe for concurrent use.
385+ //
386+ // EXPERIMENTAL: Subject to change/removal.
387+ func (cfg * Config ) CacheUnmanagedCertificatePEMBytesAsReplacement (ctx context.Context , certBytes , keyBytes []byte , tags , sans []string ) (string , error ) {
388+ cert , err := cfg .makeCertificateWithOCSP (ctx , certBytes , keyBytes )
389+ if err != nil {
390+ return "" , err
391+ }
392+ cert .Tags = tags
393+ if len (sans ) > 0 {
394+ cert .Names = sans
395+ }
396+ cfg .certCache .mu .Lock ()
397+ for _ , san := range cert .Names {
398+ existingCerts := cfg .certCache .getAllMatchingCerts (san )
399+ for _ , existingCert := range existingCerts {
400+ cfg .certCache .removeCertificate (existingCert )
401+ }
402+ }
403+ cfg .certCache .unsyncedCacheCertificate (cert )
404+ cfg .certCache .mu .Unlock ()
405+ cfg .emit (ctx , "cached_unmanaged_cert" , map [string ]any {"sans" : cert .Names , "replacement" : true })
406+ return cert .hash , nil
407+ }
408+
378409// makeCertificateFromDiskWithOCSP makes a Certificate by loading the
379410// certificate and key files. It fills out all the fields in
380411// the certificate except for the Managed and OnDemand flags.
0 commit comments