@@ -47,7 +47,10 @@ func TestDNSAccount01HappyPath(t *testing.T) {
4747 t .Fatalf ("adding DNS response: %s" , err )
4848 }
4949 t .Cleanup (func () {
50- _ , _ = testSrvClient .RemoveDNSAccount01Response (c .Account .URL , domain )
50+ _ , err := testSrvClient .RemoveDNSAccount01Response (c .Account .URL , domain )
51+ if err != nil {
52+ t .Fatal (err )
53+ }
5154 })
5255
5356 chal , err = c .Client .UpdateChallenge (c .Account , chal )
@@ -103,7 +106,10 @@ func TestDNSAccount01WrongTXTRecord(t *testing.T) {
103106 t .Fatalf ("adding DNS response: %s" , err )
104107 }
105108 t .Cleanup (func () {
106- _ , _ = testSrvClient .RemoveDNSAccount01Response (c .Account .URL , domain )
109+ _ , err := testSrvClient .RemoveDNSAccount01Response (c .Account .URL , domain )
110+ if err != nil {
111+ t .Fatal (err )
112+ }
107113 })
108114
109115 _ , err = c .Client .UpdateChallenge (c .Account , chal )
@@ -212,7 +218,10 @@ func TestDNSAccount01MultipleTXTRecordsNoneMatch(t *testing.T) {
212218 t .Fatalf ("adding DNS response: %s" , err )
213219 }
214220 t .Cleanup (func () {
215- _ , _ = testSrvClient .RemoveDNSAccount01Response (c .Account .URL , domain )
221+ _ , err := testSrvClient .RemoveDNSAccount01Response (c .Account .URL , domain )
222+ if err != nil {
223+ t .Fatal (err )
224+ }
216225 })
217226
218227 _ , err = c .Client .UpdateChallenge (c .Account , chal )
@@ -276,7 +285,10 @@ func TestDNSAccount01MultipleTXTRecordsOneMatches(t *testing.T) {
276285 t .Fatalf ("adding DNS response: %s" , err )
277286 }
278287 t .Cleanup (func () {
279- _ , _ = testSrvClient .RemoveDNSAccount01Response (c .Account .URL , domain )
288+ _ , err := testSrvClient .RemoveDNSAccount01Response (c .Account .URL , domain )
289+ if err != nil {
290+ t .Fatal (err )
291+ }
280292 })
281293
282294 chal , err = c .Client .UpdateChallenge (c .Account , chal )
@@ -342,7 +354,10 @@ func TestDNSAccount01WildcardDomain(t *testing.T) {
342354 t .Fatalf ("adding DNS response: %s" , err )
343355 }
344356 t .Cleanup (func () {
345- _ , _ = testSrvClient .RemoveDNSAccount01Response (c .Account .URL , domain )
357+ _ , err := testSrvClient .RemoveDNSAccount01Response (c .Account .URL , domain )
358+ if err != nil {
359+ t .Fatal (err )
360+ }
346361 })
347362
348363 chal , err = c .Client .UpdateChallenge (c .Account , chal )
@@ -361,3 +376,96 @@ func TestDNSAccount01WildcardDomain(t *testing.T) {
361376 }
362377 }
363378}
379+
380+ func TestDNSAccount01WildcardAuthorizationReuse (t * testing.T ) {
381+ t .Parallel ()
382+
383+ if os .Getenv ("BOULDER_CONFIG_DIR" ) == "test/config" {
384+ t .Skip ("Test requires dns-account-01 to be enabled" )
385+ }
386+
387+ // Use same domain for both orders to trigger authorization reuse
388+ domain := random_domain ()
389+ wildcardDomain := fmt .Sprintf ("*.%s" , domain )
390+
391+ c , err := makeClient ()
392+ if err != nil {
393+ t .Fatalf ("creating client: %s" , err )
394+ }
395+
396+ idents := []acme.Identifier {{Type : "dns" , Value : wildcardDomain }}
397+
398+ // First order: Create and complete DNS-Account-01 challenge
399+ order1 , err := c .Client .NewOrder (c .Account , idents )
400+ if err != nil {
401+ t .Fatalf ("creating first order: %s" , err )
402+ }
403+
404+ authzURL := order1 .Authorizations [0 ]
405+ auth1 , err := c .Client .FetchAuthorization (c .Account , authzURL )
406+ if err != nil {
407+ t .Fatalf ("fetching first authorization: %s" , err )
408+ }
409+
410+ chal , ok := auth1 .ChallengeMap [acme .ChallengeTypeDNSAccount01 ]
411+ if ! ok {
412+ t .Fatal ("dns-account-01 challenge not offered by server" )
413+ }
414+
415+ _ , err = testSrvClient .AddDNSAccount01Response (c .Account .URL , domain , chal .KeyAuthorization )
416+ if err != nil {
417+ t .Fatalf ("adding DNS response: %s" , err )
418+ }
419+ t .Cleanup (func () {
420+ _ , err := testSrvClient .RemoveDNSAccount01Response (c .Account .URL , domain )
421+ if err != nil {
422+ t .Fatal (err )
423+ }
424+ })
425+
426+ chal , err = c .Client .UpdateChallenge (c .Account , chal )
427+ if err != nil {
428+ t .Fatalf ("updating challenge: %s" , err )
429+ }
430+
431+ // Wait for authorization to become valid
432+ auth1 , err = c .Client .FetchAuthorization (c .Account , authzURL )
433+ if err != nil {
434+ t .Fatalf ("fetching first authorization after challenge update: %s" , err )
435+ }
436+
437+ if auth1 .Status != "valid" {
438+ t .Fatalf ("expected first authorization status to be 'valid', got '%s'" , auth1 .Status )
439+ }
440+
441+ // Second order: Should reuse the existing authorization
442+ order2 , err := c .Client .NewOrder (c .Account , idents )
443+ if err != nil {
444+ t .Fatalf ("creating second order: %s" , err )
445+ }
446+
447+ if len (order2 .Authorizations ) != 1 {
448+ t .Fatalf ("expected 1 authorization in second order, got %d" , len (order2 .Authorizations ))
449+ }
450+
451+ authzURL2 := order2 .Authorizations [0 ]
452+ auth2 , err := c .Client .FetchAuthorization (c .Account , authzURL2 )
453+ if err != nil {
454+ t .Fatalf ("fetching second authorization: %s" , err )
455+ }
456+
457+ // Verify reuse occurred: same authorization URL
458+ if authzURL != authzURL2 {
459+ t .Errorf ("expected same authorization URL, got different: %s != %s" , authzURL , authzURL2 )
460+ }
461+
462+ // Verify authorization is already valid (no re-validation needed)
463+ if auth2 .Status != "valid" {
464+ t .Errorf ("expected reused authorization status to be 'valid', got '%s'" , auth2 .Status )
465+ }
466+
467+ // Verify authorization still has DNS-Account-01 challenge
468+ if _ , ok := auth2 .ChallengeMap [acme .ChallengeTypeDNSAccount01 ]; ! ok {
469+ t .Error ("expected reused authorization to have dns-account-01 challenge" )
470+ }
471+ }
0 commit comments