@@ -25,7 +25,7 @@ func TestPathCerts_ExistingCertificate(t *testing.T) {
2525
2626 path := MakeDNS01Path (account , provider , fqdn )
2727 notAfter := time .Now ().Add (90 * 24 * time .Hour )
28- leaf , key := generateSelfSignedCert (t , fqdn , nil , notAfter )
28+ leaf , key := generateSelfSignedCert (t , fqdn , nil , time . Now (), notAfter )
2929
3030 originalCert := & cert {
3131 CertificateChain : []* x509.Certificate {leaf },
@@ -236,7 +236,7 @@ func TestPathCerts_Renew(t *testing.T) {
236236 require .NoError (t , resp .Error ())
237237
238238 notAfter := time .Now ().Add (- time .Hour )
239- leaf , key := generateSelfSignedCert (t , fqdn , nil , notAfter )
239+ leaf , key := generateSelfSignedCert (t , fqdn , nil , time . Now (), notAfter )
240240
241241 originalCert := & cert {
242242 CertificateChain : []* x509.Certificate {leaf },
@@ -354,7 +354,7 @@ func TestPathCerts_LeaseRevoke(t *testing.T) {
354354
355355 path := MakeDNS01Path (account , provider , fqdn )
356356 notAfter := time .Now ().Add (90 * 24 * time .Hour )
357- leaf , key := generateSelfSignedCert (t , fqdn , nil , notAfter )
357+ leaf , key := generateSelfSignedCert (t , fqdn , nil , time . Now (), notAfter )
358358
359359 originalCert := & cert {
360360 CertificateChain : []* x509.Certificate {leaf },
@@ -500,3 +500,144 @@ func TestPathCerts_IssuesNew_Wildcard(t *testing.T) {
500500 assert .Contains (t , certcrypto .ExtractDomains (certs [0 ]), fqdn )
501501 assertCertMatchesKey (t , certs [0 ], key )
502502}
503+
504+ func TestPathCerts_Renews_TwoThirds (t * testing.T ) {
505+ type testCase struct {
506+ Desc string
507+ NotBefore time.Time
508+ NotAfter time.Time
509+ ShouldRenew bool
510+ }
511+
512+ tests := []testCase {
513+ // Current 90 day certs
514+ {
515+ Desc : "90d-cert do-not-renew" ,
516+ NotBefore : time .Now (),
517+ NotAfter : time .Now ().Add (90 * 24 * time .Hour ),
518+ ShouldRenew : false ,
519+ },
520+ {
521+ Desc : "90d-cert needs-renew" ,
522+ NotBefore : time .Now ().Add (- 61 * 24 * time .Hour ),
523+ NotAfter : time .Now ().Add (29 * 24 * time .Hour ),
524+ ShouldRenew : true ,
525+ },
526+
527+ // Current shortlived (6 day) certs
528+ {
529+ Desc : "6d-cert do-not-renew" ,
530+ NotBefore : time .Now (),
531+ NotAfter : time .Now ().Add (6 * 24 * time .Hour ),
532+ ShouldRenew : false ,
533+ },
534+ {
535+ Desc : "6d-cert needs-renew" ,
536+ NotBefore : time .Now ().Add (- 5 * 24 * time .Hour ),
537+ NotAfter : time .Now ().Add (1 * 24 * time .Hour ),
538+ ShouldRenew : true ,
539+ },
540+
541+ // Future 64 day certs
542+ {
543+ Desc : "64d-cert do-not-renew" ,
544+ NotBefore : time .Now (),
545+ NotAfter : time .Now ().Add (64 * 24 * time .Hour ),
546+ ShouldRenew : false ,
547+ },
548+ {
549+ Desc : "64d-cert needs-renew" ,
550+ NotBefore : time .Now ().Add (- 41 * 24 * time .Hour ),
551+ NotAfter : time .Now ().Add (20 * 24 * time .Hour ),
552+ ShouldRenew : true ,
553+ },
554+
555+ // Future 45 day certs
556+ {
557+ Desc : "45d-cert do-not-renew" ,
558+ NotBefore : time .Now (),
559+ NotAfter : time .Now ().Add (45 * 24 * time .Hour ),
560+ ShouldRenew : false ,
561+ },
562+ {
563+ Desc : "45d-cert needs-renew" ,
564+ NotBefore : time .Now ().Add (- 31 * 24 * time .Hour ),
565+ NotAfter : time .Now ().Add (14 * 24 * time .Hour ),
566+ ShouldRenew : true ,
567+ },
568+ }
569+
570+ for _ , tc := range tests {
571+
572+ func () {
573+ b := createTestBackend (t )
574+
575+ as := b .startACMEServer (t )
576+ defer as .Close ()
577+
578+ const (
579+ account = "test-account"
580+ provider = "test-dns"
581+ fqdn = "test.example.com"
582+ )
583+
584+ path := MakeDNS01Path (account , provider , fqdn )
585+
586+ b .RegisterDNSProvider (provider , func () (challenge.Provider , error ) {
587+ return as , nil
588+ })
589+
590+ accountPath := "accounts/" + account
591+ req := & logical.Request {
592+ Path : accountPath ,
593+ Operation : logical .UpdateOperation ,
594+ Data : map [string ]interface {}{
595+ 596+ "directory_url" : as .DirectoryURL ,
597+ "tos_agreed" : true ,
598+ },
599+ }
600+
601+ resp , err := b .HandleRequest (t , req )
602+ require .NoError (t , err )
603+ require .NotNil (t , resp )
604+ require .NoError (t , resp .Error ())
605+
606+ leaf , key := generateSelfSignedCert (t , fqdn , nil , tc .NotBefore , tc .NotAfter )
607+
608+ originalCert := & cert {
609+ CertificateChain : []* x509.Certificate {leaf },
610+ Key : key ,
611+ }
612+ err = originalCert .write (t .Context (), b .Storage , path )
613+ require .NoError (t , err )
614+
615+ req = & logical.Request {
616+ Path : path ,
617+ Operation : logical .ReadOperation ,
618+ }
619+
620+ resp , err = b .HandleRequest (t , req )
621+ require .NoError (t , err )
622+ require .NotNil (t , resp )
623+ require .NoError (t , resp .Error ())
624+
625+ certs , err := certcrypto .ParsePEMBundle ([]byte (resp .Data ["certificate" ].(string )))
626+ require .NoError (t , err )
627+ require .NotEmpty (t , certs )
628+
629+ privKey , err := certcrypto .ParsePEMPrivateKey ([]byte (resp .Data ["private_key" ].(string )))
630+ require .NoError (t , err )
631+ require .NotNil (t , privKey )
632+
633+ assert .Contains (t , certcrypto .ExtractDomains (certs [0 ]), fqdn )
634+ if tc .ShouldRenew {
635+ assertCertMatchesKey (t , certs [0 ], privKey )
636+ assert .Truef (t , certs [0 ].NotAfter .After (tc .NotAfter ), "%s" , tc .Desc )
637+ } else {
638+ assert .Equalf (t , tc .NotAfter .Year (), certs [0 ].NotAfter .Year (), tc .Desc )
639+ assert .Equalf (t , tc .NotAfter .YearDay (), certs [0 ].NotAfter .YearDay (), tc .Desc )
640+ }
641+ }()
642+ }
643+ }
0 commit comments