github.com/letsencrypt/boulder@v0.20251208.0/core/objects_test.go (about) 1 package core 2 3 import ( 4 "crypto/rsa" 5 "encoding/json" 6 "math/big" 7 "net/netip" 8 "testing" 9 "time" 10 11 "github.com/go-jose/go-jose/v4" 12 13 "github.com/letsencrypt/boulder/test" 14 ) 15 16 func TestExpectedKeyAuthorization(t *testing.T) { 17 ch := Challenge{Token: "hi"} 18 jwk1 := &jose.JSONWebKey{Key: &rsa.PublicKey{N: big.NewInt(1234), E: 1234}} 19 jwk2 := &jose.JSONWebKey{Key: &rsa.PublicKey{N: big.NewInt(5678), E: 5678}} 20 21 ka1, err := ch.ExpectedKeyAuthorization(jwk1) 22 test.AssertNotError(t, err, "Failed to calculate expected key authorization 1") 23 ka2, err := ch.ExpectedKeyAuthorization(jwk2) 24 test.AssertNotError(t, err, "Failed to calculate expected key authorization 2") 25 26 expected1 := "hi.sIMEyhkWCCSYqDqZqPM1bKkvb5T9jpBOb7_w5ZNorF4" 27 expected2 := "hi.FPoiyqWPod2T0fKqkPI1uXPYUsRK1DSyzsQsv0oMuGg" 28 if ka1 != expected1 { 29 t.Errorf("Incorrect ka1. Expected [%s], got [%s]", expected1, ka1) 30 } 31 if ka2 != expected2 { 32 t.Errorf("Incorrect ka2. Expected [%s], got [%s]", expected2, ka2) 33 } 34 } 35 36 func TestRecordSanityCheckOnUnsupportedChallengeType(t *testing.T) { 37 rec := []ValidationRecord{ 38 { 39 URL: "http://localhost/test", 40 Hostname: "localhost", 41 Port: "80", 42 AddressesResolved: []netip.Addr{netip.MustParseAddr("127.0.0.1")}, 43 AddressUsed: netip.MustParseAddr("127.0.0.1"), 44 ResolverAddrs: []string{"eastUnboundAndDown"}, 45 }, 46 } 47 48 chall := Challenge{Type: "obsoletedChallenge", ValidationRecord: rec} 49 test.Assert(t, !chall.RecordsSane(), "Record with unsupported challenge type should not be sane") 50 } 51 52 func TestChallengeSanityCheck(t *testing.T) { 53 // Make a temporary account key 54 var accountKey *jose.JSONWebKey 55 err := json.Unmarshal([]byte(`{ 56 "kty":"RSA", 57 "n":"yNWVhtYEKJR21y9xsHV-PD_bYwbXSeNuFal46xYxVfRL5mqha7vttvjB_vc7Xg2RvgCxHPCqoxgMPTzHrZT75LjCwIW2K_klBYN8oYvTwwmeSkAz6ut7ZxPv-nZaT5TJhGk0NT2kh_zSpdriEJ_3vW-mqxYbbBmpvHqsa1_zx9fSuHYctAZJWzxzUZXykbWMWQZpEiE0J4ajj51fInEzVn7VxV-mzfMyboQjujPh7aNJxAWSq4oQEJJDgWwSh9leyoJoPpONHxh5nEE5AjE01FkGICSxjpZsF-w8hOTI3XXohUdu29Se26k2B0PolDSuj0GIQU6-W9TdLXSjBb2SpQ", 58 "e":"AQAB" 59 }`), &accountKey) 60 test.AssertNotError(t, err, "Error unmarshaling JWK") 61 62 types := []AcmeChallenge{ChallengeTypeHTTP01, ChallengeTypeDNS01, ChallengeTypeTLSALPN01, ChallengeTypeDNSAccount01} 63 for _, challengeType := range types { 64 chall := Challenge{ 65 Type: challengeType, 66 Status: StatusInvalid, 67 } 68 test.AssertError(t, chall.CheckPending(), "CheckConsistencyForClientOffer didn't return an error") 69 70 chall.Status = StatusPending 71 test.AssertError(t, chall.CheckPending(), "CheckConsistencyForClientOffer didn't return an error") 72 73 chall.Token = "KQqLsiS5j0CONR_eUXTUSUDNVaHODtc-0pD6ACif7U4" 74 test.AssertNotError(t, chall.CheckPending(), "CheckConsistencyForClientOffer returned an error") 75 } 76 } 77 78 func TestJSONBufferUnmarshal(t *testing.T) { 79 testStruct := struct { 80 Buffer JSONBuffer 81 }{} 82 83 notValidBase64 := []byte(`{"Buffer":"!!!!"}`) 84 err := json.Unmarshal(notValidBase64, &testStruct) 85 test.Assert(t, err != nil, "Should have choked on invalid base64") 86 } 87 88 func TestAuthorizationSolvedBy(t *testing.T) { 89 validHTTP01 := HTTPChallenge01("") 90 validHTTP01.Status = StatusValid 91 validDNS01 := DNSChallenge01("") 92 validDNS01.Status = StatusValid 93 testCases := []struct { 94 Name string 95 Authz Authorization 96 ExpectedResult AcmeChallenge 97 ExpectedError string 98 }{ 99 // An authz with no challenges should return nil 100 { 101 Name: "No challenges", 102 Authz: Authorization{}, 103 ExpectedError: "authorization has no challenges", 104 }, 105 // An authz with all non-valid challenges should return nil 106 { 107 Name: "All non-valid challenges", 108 Authz: Authorization{ 109 Challenges: []Challenge{HTTPChallenge01(""), DNSChallenge01("")}, 110 }, 111 ExpectedError: "authorization not solved by any challenge", 112 }, 113 // An authz with one valid HTTP01 challenge amongst other challenges should 114 // return the HTTP01 challenge 115 { 116 Name: "Valid HTTP01 challenge", 117 Authz: Authorization{ 118 Challenges: []Challenge{HTTPChallenge01(""), validHTTP01, DNSChallenge01("")}, 119 }, 120 ExpectedResult: ChallengeTypeHTTP01, 121 }, 122 // An authz with both a valid HTTP01 challenge and a valid DNS01 challenge 123 // among other challenges should return whichever valid challenge is first 124 // (in this case DNS01) 125 { 126 Name: "Valid HTTP01 and DNS01 challenge", 127 Authz: Authorization{ 128 Challenges: []Challenge{validDNS01, HTTPChallenge01(""), validHTTP01, DNSChallenge01("")}, 129 }, 130 ExpectedResult: ChallengeTypeDNS01, 131 }, 132 } 133 134 for _, tc := range testCases { 135 t.Run(tc.Name, func(t *testing.T) { 136 result, err := tc.Authz.SolvedBy() 137 if tc.ExpectedError != "" { 138 test.AssertEquals(t, err.Error(), tc.ExpectedError) 139 } 140 if tc.ExpectedResult != "" { 141 test.AssertEquals(t, result, tc.ExpectedResult) 142 } 143 }) 144 } 145 } 146 147 func TestChallengeStringID(t *testing.T) { 148 ch := Challenge{ 149 Token: "asd", 150 Type: ChallengeTypeDNS01, 151 } 152 test.AssertEquals(t, ch.StringID(), "iFVMwA") 153 ch.Type = ChallengeTypeHTTP01 154 test.AssertEquals(t, ch.StringID(), "0Gexug") 155 ch.Type = ChallengeTypeDNSAccount01 156 test.AssertEquals(t, ch.StringID(), "8z2wSg") 157 } 158 159 func TestFindChallengeByType(t *testing.T) { 160 authz := Authorization{ 161 Challenges: []Challenge{ 162 {Token: "woo", Type: ChallengeTypeDNS01}, 163 {Token: "woo", Type: ChallengeTypeHTTP01}, 164 }, 165 } 166 test.AssertEquals(t, 0, authz.FindChallengeByStringID(authz.Challenges[0].StringID())) 167 test.AssertEquals(t, 1, authz.FindChallengeByStringID(authz.Challenges[1].StringID())) 168 test.AssertEquals(t, -1, authz.FindChallengeByStringID("hello")) 169 } 170 171 func TestRenewalInfoSuggestedWindowIsWithin(t *testing.T) { 172 now := time.Now().UTC() 173 window := SuggestedWindow{ 174 Start: now, 175 End: now.Add(time.Hour), 176 } 177 178 // Exactly the beginning, inclusive of the first nanosecond. 179 test.Assert(t, window.IsWithin(now), "Start of window should be within the window") 180 181 // Exactly the middle. 182 test.Assert(t, window.IsWithin(now.Add(time.Minute*30)), "Middle of window should be within the window") 183 184 // Exactly the end time. 185 test.Assert(t, !window.IsWithin(now.Add(time.Hour)), "End of window should be outside the window") 186 187 // Exactly the end of the window. 188 test.Assert(t, window.IsWithin(now.Add(time.Hour-time.Nanosecond)), "Should be just inside the window") 189 190 // Just before the first nanosecond. 191 test.Assert(t, !window.IsWithin(now.Add(-time.Nanosecond)), "Before the window should not be within the window") 192 }