renewal_test.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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. timeNow = func() time.Time { return now }
  23. defer func() { timeNow = time.Now }()
  24. man := &Manager{RenewBefore: 7 * 24 * time.Hour}
  25. defer man.stopRenew()
  26. tt := []struct {
  27. expiry time.Time
  28. min, max time.Duration
  29. }{
  30. {now.Add(90 * 24 * time.Hour), 83*24*time.Hour - renewJitter, 83 * 24 * time.Hour},
  31. {now.Add(time.Hour), 0, 1},
  32. {now, 0, 1},
  33. {now.Add(-time.Hour), 0, 1},
  34. }
  35. dr := &domainRenewal{m: man}
  36. for i, test := range tt {
  37. next := dr.next(test.expiry)
  38. if next < test.min || test.max < next {
  39. t.Errorf("%d: next = %v; want between %v and %v", i, next, test.min, test.max)
  40. }
  41. }
  42. }
  43. func TestRenewFromCache(t *testing.T) {
  44. const domain = "example.org"
  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. // cert request
  68. case "/new-cert":
  69. var req struct {
  70. CSR string `json:"csr"`
  71. }
  72. decodePayload(&req, r.Body)
  73. b, _ := base64.RawURLEncoding.DecodeString(req.CSR)
  74. csr, err := x509.ParseCertificateRequest(b)
  75. if err != nil {
  76. t.Fatalf("new-cert: CSR: %v", err)
  77. }
  78. der, err := dummyCert(csr.PublicKey, domain)
  79. if err != nil {
  80. t.Fatalf("new-cert: dummyCert: %v", err)
  81. }
  82. chainUp := fmt.Sprintf("<%s/ca-cert>; rel=up", ca.URL)
  83. w.Header().Set("Link", chainUp)
  84. w.WriteHeader(http.StatusCreated)
  85. w.Write(der)
  86. // CA chain cert
  87. case "/ca-cert":
  88. der, err := dummyCert(nil, "ca")
  89. if err != nil {
  90. t.Fatalf("ca-cert: dummyCert: %v", err)
  91. }
  92. w.Write(der)
  93. default:
  94. t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path)
  95. }
  96. }))
  97. defer ca.Close()
  98. // use EC key to run faster on 386
  99. key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  100. if err != nil {
  101. t.Fatal(err)
  102. }
  103. man := &Manager{
  104. Prompt: AcceptTOS,
  105. Cache: newMemCache(),
  106. RenewBefore: 24 * time.Hour,
  107. Client: &acme.Client{
  108. Key: key,
  109. DirectoryURL: ca.URL,
  110. },
  111. }
  112. defer man.stopRenew()
  113. // cache an almost expired cert
  114. now := time.Now()
  115. cert, err := dateDummyCert(key.Public(), now.Add(-2*time.Hour), now.Add(time.Minute), domain)
  116. if err != nil {
  117. t.Fatal(err)
  118. }
  119. tlscert := &tls.Certificate{PrivateKey: key, Certificate: [][]byte{cert}}
  120. if err := man.cachePut(context.Background(), domain, tlscert); err != nil {
  121. t.Fatal(err)
  122. }
  123. // veriy the renewal happened
  124. defer func() {
  125. testDidRenewLoop = func(next time.Duration, err error) {}
  126. }()
  127. done := make(chan struct{})
  128. testDidRenewLoop = func(next time.Duration, err error) {
  129. defer close(done)
  130. if err != nil {
  131. t.Errorf("testDidRenewLoop: %v", err)
  132. }
  133. // Next should be about 90 days:
  134. // dummyCert creates 90days expiry + account for man.RenewBefore.
  135. // Previous expiration was within 1 min.
  136. future := 88 * 24 * time.Hour
  137. if next < future {
  138. t.Errorf("testDidRenewLoop: next = %v; want >= %v", next, future)
  139. }
  140. // ensure the new cert is cached
  141. after := time.Now().Add(future)
  142. tlscert, err := man.cacheGet(context.Background(), domain)
  143. if err != nil {
  144. t.Fatalf("man.cacheGet: %v", err)
  145. }
  146. if !tlscert.Leaf.NotAfter.After(after) {
  147. t.Errorf("cache leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after)
  148. }
  149. // verify the old cert is also replaced in memory
  150. man.stateMu.Lock()
  151. defer man.stateMu.Unlock()
  152. s := man.state[domain]
  153. if s == nil {
  154. t.Fatalf("m.state[%q] is nil", domain)
  155. }
  156. tlscert, err = s.tlscert()
  157. if err != nil {
  158. t.Fatalf("s.tlscert: %v", err)
  159. }
  160. if !tlscert.Leaf.NotAfter.After(after) {
  161. t.Errorf("state leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after)
  162. }
  163. }
  164. // trigger renew
  165. hello := &tls.ClientHelloInfo{ServerName: domain}
  166. if _, err := man.GetCertificate(hello); err != nil {
  167. t.Fatal(err)
  168. }
  169. // wait for renew loop
  170. select {
  171. case <-time.After(10 * time.Second):
  172. t.Fatal("renew took too long to occur")
  173. case <-done:
  174. }
  175. }
  176. func TestRenewFromCacheAlreadyRenewed(t *testing.T) {
  177. const domain = "example.org"
  178. // use EC key to run faster on 386
  179. key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  180. if err != nil {
  181. t.Fatal(err)
  182. }
  183. man := &Manager{
  184. Prompt: AcceptTOS,
  185. Cache: newMemCache(),
  186. RenewBefore: 24 * time.Hour,
  187. Client: &acme.Client{
  188. Key: key,
  189. DirectoryURL: "invalid",
  190. },
  191. }
  192. defer man.stopRenew()
  193. // cache a recently renewed cert with a different private key
  194. newKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  195. if err != nil {
  196. t.Fatal(err)
  197. }
  198. now := time.Now()
  199. newCert, err := dateDummyCert(newKey.Public(), now.Add(-2*time.Hour), now.Add(time.Hour*24*90), domain)
  200. if err != nil {
  201. t.Fatal(err)
  202. }
  203. newLeaf, err := validCert(domain, [][]byte{newCert}, newKey)
  204. if err != nil {
  205. t.Fatal(err)
  206. }
  207. newTLSCert := &tls.Certificate{PrivateKey: newKey, Certificate: [][]byte{newCert}, Leaf: newLeaf}
  208. if err := man.cachePut(context.Background(), domain, newTLSCert); err != nil {
  209. t.Fatal(err)
  210. }
  211. // set internal state to an almost expired cert
  212. oldCert, err := dateDummyCert(key.Public(), now.Add(-2*time.Hour), now.Add(time.Minute), domain)
  213. if err != nil {
  214. t.Fatal(err)
  215. }
  216. oldLeaf, err := validCert(domain, [][]byte{oldCert}, key)
  217. if err != nil {
  218. t.Fatal(err)
  219. }
  220. man.stateMu.Lock()
  221. if man.state == nil {
  222. man.state = make(map[string]*certState)
  223. }
  224. s := &certState{
  225. key: key,
  226. cert: [][]byte{oldCert},
  227. leaf: oldLeaf,
  228. }
  229. man.state[domain] = s
  230. man.stateMu.Unlock()
  231. // veriy the renewal accepted the newer cached cert
  232. defer func() {
  233. testDidRenewLoop = func(next time.Duration, err error) {}
  234. }()
  235. done := make(chan struct{})
  236. testDidRenewLoop = func(next time.Duration, err error) {
  237. defer close(done)
  238. if err != nil {
  239. t.Errorf("testDidRenewLoop: %v", err)
  240. }
  241. // Next should be about 90 days
  242. // Previous expiration was within 1 min.
  243. future := 88 * 24 * time.Hour
  244. if next < future {
  245. t.Errorf("testDidRenewLoop: next = %v; want >= %v", next, future)
  246. }
  247. // ensure the cached cert was not modified
  248. tlscert, err := man.cacheGet(context.Background(), domain)
  249. if err != nil {
  250. t.Fatalf("man.cacheGet: %v", err)
  251. }
  252. if !tlscert.Leaf.NotAfter.Equal(newLeaf.NotAfter) {
  253. t.Errorf("cache leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newLeaf.NotAfter)
  254. }
  255. // verify the old cert is also replaced in memory
  256. man.stateMu.Lock()
  257. defer man.stateMu.Unlock()
  258. s := man.state[domain]
  259. if s == nil {
  260. t.Fatalf("m.state[%q] is nil", domain)
  261. }
  262. stateKey := s.key.Public().(*ecdsa.PublicKey)
  263. if stateKey.X.Cmp(newKey.X) != 0 || stateKey.Y.Cmp(newKey.Y) != 0 {
  264. 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)
  265. }
  266. tlscert, err = s.tlscert()
  267. if err != nil {
  268. t.Fatalf("s.tlscert: %v", err)
  269. }
  270. if !tlscert.Leaf.NotAfter.Equal(newLeaf.NotAfter) {
  271. t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newLeaf.NotAfter)
  272. }
  273. // verify the private key is replaced in the renewal state
  274. r := man.renewal[domain]
  275. if r == nil {
  276. t.Fatalf("m.renewal[%q] is nil", domain)
  277. }
  278. renewalKey := r.key.Public().(*ecdsa.PublicKey)
  279. if renewalKey.X.Cmp(newKey.X) != 0 || renewalKey.Y.Cmp(newKey.Y) != 0 {
  280. 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)
  281. }
  282. }
  283. // assert the expiring cert is returned from state
  284. hello := &tls.ClientHelloInfo{ServerName: domain}
  285. tlscert, err := man.GetCertificate(hello)
  286. if err != nil {
  287. t.Fatal(err)
  288. }
  289. if !oldLeaf.NotAfter.Equal(tlscert.Leaf.NotAfter) {
  290. t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, oldLeaf.NotAfter)
  291. }
  292. // trigger renew
  293. go man.renew(domain, s.key, s.leaf.NotAfter)
  294. // wait for renew loop
  295. select {
  296. case <-time.After(10 * time.Second):
  297. t.Fatal("renew took too long to occur")
  298. case <-done:
  299. // assert the new cert is returned from state after renew
  300. hello := &tls.ClientHelloInfo{ServerName: domain}
  301. tlscert, err := man.GetCertificate(hello)
  302. if err != nil {
  303. t.Fatal(err)
  304. }
  305. if !newTLSCert.Leaf.NotAfter.Equal(tlscert.Leaf.NotAfter) {
  306. t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newTLSCert.Leaf.NotAfter)
  307. }
  308. }
  309. }