renewal_test.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. // Copyright 2016 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package autocert
  5. import (
  6. "context"
  7. "crypto/ecdsa"
  8. "crypto/elliptic"
  9. "crypto/rand"
  10. "crypto/tls"
  11. "crypto/x509"
  12. "encoding/base64"
  13. "fmt"
  14. "net/http"
  15. "net/http/httptest"
  16. "testing"
  17. "time"
  18. "golang.org/x/crypto/acme"
  19. )
  20. func TestRenewalNext(t *testing.T) {
  21. now := time.Now()
  22. man := &Manager{
  23. RenewBefore: 7 * 24 * time.Hour,
  24. nowFunc: func() time.Time { return now },
  25. }
  26. defer man.stopRenew()
  27. tt := []struct {
  28. expiry time.Time
  29. min, max time.Duration
  30. }{
  31. {now.Add(90 * 24 * time.Hour), 83*24*time.Hour - renewJitter, 83 * 24 * time.Hour},
  32. {now.Add(time.Hour), 0, 1},
  33. {now, 0, 1},
  34. {now.Add(-time.Hour), 0, 1},
  35. }
  36. dr := &domainRenewal{m: man}
  37. for i, test := range tt {
  38. next := dr.next(test.expiry)
  39. if next < test.min || test.max < next {
  40. t.Errorf("%d: next = %v; want between %v and %v", i, next, test.min, test.max)
  41. }
  42. }
  43. }
  44. func TestRenewFromCache(t *testing.T) {
  45. // ACME CA server stub
  46. var ca *httptest.Server
  47. ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  48. w.Header().Set("Replay-Nonce", "nonce")
  49. if r.Method == "HEAD" {
  50. // a nonce request
  51. return
  52. }
  53. switch r.URL.Path {
  54. // discovery
  55. case "/":
  56. if err := discoTmpl.Execute(w, ca.URL); err != nil {
  57. t.Fatalf("discoTmpl: %v", err)
  58. }
  59. // client key registration
  60. case "/new-reg":
  61. w.Write([]byte("{}"))
  62. // domain authorization
  63. case "/new-authz":
  64. w.Header().Set("Location", ca.URL+"/authz/1")
  65. w.WriteHeader(http.StatusCreated)
  66. w.Write([]byte(`{"status": "valid"}`))
  67. // authorization status request done by Manager's revokePendingAuthz.
  68. case "/authz/1":
  69. w.Write([]byte(`{"status": "valid"}`))
  70. // cert request
  71. case "/new-cert":
  72. var req struct {
  73. CSR string `json:"csr"`
  74. }
  75. decodePayload(&req, r.Body)
  76. b, _ := base64.RawURLEncoding.DecodeString(req.CSR)
  77. csr, err := x509.ParseCertificateRequest(b)
  78. if err != nil {
  79. t.Fatalf("new-cert: CSR: %v", err)
  80. }
  81. der, err := dummyCert(csr.PublicKey, exampleDomain)
  82. if err != nil {
  83. t.Fatalf("new-cert: dummyCert: %v", err)
  84. }
  85. chainUp := fmt.Sprintf("<%s/ca-cert>; rel=up", ca.URL)
  86. w.Header().Set("Link", chainUp)
  87. w.WriteHeader(http.StatusCreated)
  88. w.Write(der)
  89. // CA chain cert
  90. case "/ca-cert":
  91. der, err := dummyCert(nil, "ca")
  92. if err != nil {
  93. t.Fatalf("ca-cert: dummyCert: %v", err)
  94. }
  95. w.Write(der)
  96. default:
  97. t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path)
  98. }
  99. }))
  100. defer ca.Close()
  101. man := &Manager{
  102. Prompt: AcceptTOS,
  103. Cache: newMemCache(t),
  104. RenewBefore: 24 * time.Hour,
  105. Client: &acme.Client{
  106. DirectoryURL: ca.URL,
  107. },
  108. }
  109. defer man.stopRenew()
  110. // cache an almost expired cert
  111. key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  112. if err != nil {
  113. t.Fatal(err)
  114. }
  115. now := time.Now()
  116. cert, err := dateDummyCert(key.Public(), now.Add(-2*time.Hour), now.Add(time.Minute), exampleDomain)
  117. if err != nil {
  118. t.Fatal(err)
  119. }
  120. tlscert := &tls.Certificate{PrivateKey: key, Certificate: [][]byte{cert}}
  121. if err := man.cachePut(context.Background(), exampleCertKey, tlscert); err != nil {
  122. t.Fatal(err)
  123. }
  124. // veriy the renewal happened
  125. defer func() {
  126. testDidRenewLoop = func(next time.Duration, err error) {}
  127. }()
  128. done := make(chan struct{})
  129. testDidRenewLoop = func(next time.Duration, err error) {
  130. defer close(done)
  131. if err != nil {
  132. t.Errorf("testDidRenewLoop: %v", err)
  133. }
  134. // Next should be about 90 days:
  135. // dummyCert creates 90days expiry + account for man.RenewBefore.
  136. // Previous expiration was within 1 min.
  137. future := 88 * 24 * time.Hour
  138. if next < future {
  139. t.Errorf("testDidRenewLoop: next = %v; want >= %v", next, future)
  140. }
  141. // ensure the new cert is cached
  142. after := time.Now().Add(future)
  143. tlscert, err := man.cacheGet(context.Background(), exampleCertKey)
  144. if err != nil {
  145. t.Fatalf("man.cacheGet: %v", err)
  146. }
  147. if !tlscert.Leaf.NotAfter.After(after) {
  148. t.Errorf("cache leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after)
  149. }
  150. // verify the old cert is also replaced in memory
  151. man.stateMu.Lock()
  152. defer man.stateMu.Unlock()
  153. s := man.state[exampleCertKey]
  154. if s == nil {
  155. t.Fatalf("m.state[%q] is nil", exampleCertKey)
  156. }
  157. tlscert, err = s.tlscert()
  158. if err != nil {
  159. t.Fatalf("s.tlscert: %v", err)
  160. }
  161. if !tlscert.Leaf.NotAfter.After(after) {
  162. t.Errorf("state leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after)
  163. }
  164. }
  165. // trigger renew
  166. hello := clientHelloInfo(exampleDomain, algECDSA)
  167. if _, err := man.GetCertificate(hello); err != nil {
  168. t.Fatal(err)
  169. }
  170. // wait for renew loop
  171. select {
  172. case <-time.After(10 * time.Second):
  173. t.Fatal("renew took too long to occur")
  174. case <-done:
  175. }
  176. }
  177. func TestRenewFromCacheAlreadyRenewed(t *testing.T) {
  178. man := &Manager{
  179. Prompt: AcceptTOS,
  180. Cache: newMemCache(t),
  181. RenewBefore: 24 * time.Hour,
  182. Client: &acme.Client{
  183. DirectoryURL: "invalid",
  184. },
  185. }
  186. defer man.stopRenew()
  187. // cache a recently renewed cert with a different private key
  188. newKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  189. if err != nil {
  190. t.Fatal(err)
  191. }
  192. now := time.Now()
  193. newCert, err := dateDummyCert(newKey.Public(), now.Add(-2*time.Hour), now.Add(time.Hour*24*90), exampleDomain)
  194. if err != nil {
  195. t.Fatal(err)
  196. }
  197. newLeaf, err := validCert(exampleCertKey, [][]byte{newCert}, newKey, now)
  198. if err != nil {
  199. t.Fatal(err)
  200. }
  201. newTLSCert := &tls.Certificate{PrivateKey: newKey, Certificate: [][]byte{newCert}, Leaf: newLeaf}
  202. if err := man.cachePut(context.Background(), exampleCertKey, newTLSCert); err != nil {
  203. t.Fatal(err)
  204. }
  205. // set internal state to an almost expired cert
  206. key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  207. if err != nil {
  208. t.Fatal(err)
  209. }
  210. oldCert, err := dateDummyCert(key.Public(), now.Add(-2*time.Hour), now.Add(time.Minute), exampleDomain)
  211. if err != nil {
  212. t.Fatal(err)
  213. }
  214. oldLeaf, err := validCert(exampleCertKey, [][]byte{oldCert}, key, now)
  215. if err != nil {
  216. t.Fatal(err)
  217. }
  218. man.stateMu.Lock()
  219. if man.state == nil {
  220. man.state = make(map[certKey]*certState)
  221. }
  222. s := &certState{
  223. key: key,
  224. cert: [][]byte{oldCert},
  225. leaf: oldLeaf,
  226. }
  227. man.state[exampleCertKey] = s
  228. man.stateMu.Unlock()
  229. // veriy the renewal accepted the newer cached cert
  230. defer func() {
  231. testDidRenewLoop = func(next time.Duration, err error) {}
  232. }()
  233. done := make(chan struct{})
  234. testDidRenewLoop = func(next time.Duration, err error) {
  235. defer close(done)
  236. if err != nil {
  237. t.Errorf("testDidRenewLoop: %v", err)
  238. }
  239. // Next should be about 90 days
  240. // Previous expiration was within 1 min.
  241. future := 88 * 24 * time.Hour
  242. if next < future {
  243. t.Errorf("testDidRenewLoop: next = %v; want >= %v", next, future)
  244. }
  245. // ensure the cached cert was not modified
  246. tlscert, err := man.cacheGet(context.Background(), exampleCertKey)
  247. if err != nil {
  248. t.Fatalf("man.cacheGet: %v", err)
  249. }
  250. if !tlscert.Leaf.NotAfter.Equal(newLeaf.NotAfter) {
  251. t.Errorf("cache leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newLeaf.NotAfter)
  252. }
  253. // verify the old cert is also replaced in memory
  254. man.stateMu.Lock()
  255. defer man.stateMu.Unlock()
  256. s := man.state[exampleCertKey]
  257. if s == nil {
  258. t.Fatalf("m.state[%q] is nil", exampleCertKey)
  259. }
  260. stateKey := s.key.Public().(*ecdsa.PublicKey)
  261. if stateKey.X.Cmp(newKey.X) != 0 || stateKey.Y.Cmp(newKey.Y) != 0 {
  262. t.Fatalf("state key was not updated from cache x: %v y: %v; want x: %v y: %v", stateKey.X, stateKey.Y, newKey.X, newKey.Y)
  263. }
  264. tlscert, err = s.tlscert()
  265. if err != nil {
  266. t.Fatalf("s.tlscert: %v", err)
  267. }
  268. if !tlscert.Leaf.NotAfter.Equal(newLeaf.NotAfter) {
  269. t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newLeaf.NotAfter)
  270. }
  271. // verify the private key is replaced in the renewal state
  272. r := man.renewal[exampleCertKey]
  273. if r == nil {
  274. t.Fatalf("m.renewal[%q] is nil", exampleCertKey)
  275. }
  276. renewalKey := r.key.Public().(*ecdsa.PublicKey)
  277. if renewalKey.X.Cmp(newKey.X) != 0 || renewalKey.Y.Cmp(newKey.Y) != 0 {
  278. t.Fatalf("renewal private key was not updated from cache x: %v y: %v; want x: %v y: %v", renewalKey.X, renewalKey.Y, newKey.X, newKey.Y)
  279. }
  280. }
  281. // assert the expiring cert is returned from state
  282. hello := clientHelloInfo(exampleDomain, algECDSA)
  283. tlscert, err := man.GetCertificate(hello)
  284. if err != nil {
  285. t.Fatal(err)
  286. }
  287. if !oldLeaf.NotAfter.Equal(tlscert.Leaf.NotAfter) {
  288. t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, oldLeaf.NotAfter)
  289. }
  290. // trigger renew
  291. go man.renew(exampleCertKey, s.key, s.leaf.NotAfter)
  292. // wait for renew loop
  293. select {
  294. case <-time.After(10 * time.Second):
  295. t.Fatal("renew took too long to occur")
  296. case <-done:
  297. // assert the new cert is returned from state after renew
  298. hello := clientHelloInfo(exampleDomain, algECDSA)
  299. tlscert, err := man.GetCertificate(hello)
  300. if err != nil {
  301. t.Fatal(err)
  302. }
  303. if !newTLSCert.Leaf.NotAfter.Equal(tlscert.Leaf.NotAfter) {
  304. t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newTLSCert.Leaf.NotAfter)
  305. }
  306. }
  307. }