acme_test.go 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
  1. // Copyright 2015 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 acme
  5. import (
  6. "bytes"
  7. "context"
  8. "crypto/rand"
  9. "crypto/rsa"
  10. "crypto/tls"
  11. "crypto/x509"
  12. "crypto/x509/pkix"
  13. "encoding/base64"
  14. "encoding/json"
  15. "fmt"
  16. "math/big"
  17. "net/http"
  18. "net/http/httptest"
  19. "reflect"
  20. "sort"
  21. "strings"
  22. "testing"
  23. "time"
  24. )
  25. // Decodes a JWS-encoded request and unmarshals the decoded JSON into a provided
  26. // interface.
  27. func decodeJWSRequest(t *testing.T, v interface{}, r *http.Request) {
  28. // Decode request
  29. var req struct{ Payload string }
  30. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  31. t.Fatal(err)
  32. }
  33. payload, err := base64.RawURLEncoding.DecodeString(req.Payload)
  34. if err != nil {
  35. t.Fatal(err)
  36. }
  37. err = json.Unmarshal(payload, v)
  38. if err != nil {
  39. t.Fatal(err)
  40. }
  41. }
  42. type jwsHead struct {
  43. Alg string
  44. Nonce string
  45. JWK map[string]string `json:"jwk"`
  46. }
  47. func decodeJWSHead(r *http.Request) (*jwsHead, error) {
  48. var req struct{ Protected string }
  49. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  50. return nil, err
  51. }
  52. b, err := base64.RawURLEncoding.DecodeString(req.Protected)
  53. if err != nil {
  54. return nil, err
  55. }
  56. var head jwsHead
  57. if err := json.Unmarshal(b, &head); err != nil {
  58. return nil, err
  59. }
  60. return &head, nil
  61. }
  62. func TestDiscover(t *testing.T) {
  63. const (
  64. reg = "https://example.com/acme/new-reg"
  65. authz = "https://example.com/acme/new-authz"
  66. cert = "https://example.com/acme/new-cert"
  67. revoke = "https://example.com/acme/revoke-cert"
  68. )
  69. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  70. w.Header().Set("Content-Type", "application/json")
  71. fmt.Fprintf(w, `{
  72. "new-reg": %q,
  73. "new-authz": %q,
  74. "new-cert": %q,
  75. "revoke-cert": %q
  76. }`, reg, authz, cert, revoke)
  77. }))
  78. defer ts.Close()
  79. c := Client{DirectoryURL: ts.URL}
  80. dir, err := c.Discover(context.Background())
  81. if err != nil {
  82. t.Fatal(err)
  83. }
  84. if dir.RegURL != reg {
  85. t.Errorf("dir.RegURL = %q; want %q", dir.RegURL, reg)
  86. }
  87. if dir.AuthzURL != authz {
  88. t.Errorf("dir.AuthzURL = %q; want %q", dir.AuthzURL, authz)
  89. }
  90. if dir.CertURL != cert {
  91. t.Errorf("dir.CertURL = %q; want %q", dir.CertURL, cert)
  92. }
  93. if dir.RevokeURL != revoke {
  94. t.Errorf("dir.RevokeURL = %q; want %q", dir.RevokeURL, revoke)
  95. }
  96. }
  97. func TestRegister(t *testing.T) {
  98. contacts := []string{"mailto:admin@example.com"}
  99. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  100. if r.Method == "HEAD" {
  101. w.Header().Set("Replay-Nonce", "test-nonce")
  102. return
  103. }
  104. if r.Method != "POST" {
  105. t.Errorf("r.Method = %q; want POST", r.Method)
  106. }
  107. var j struct {
  108. Resource string
  109. Contact []string
  110. Agreement string
  111. }
  112. decodeJWSRequest(t, &j, r)
  113. // Test request
  114. if j.Resource != "new-reg" {
  115. t.Errorf("j.Resource = %q; want new-reg", j.Resource)
  116. }
  117. if !reflect.DeepEqual(j.Contact, contacts) {
  118. t.Errorf("j.Contact = %v; want %v", j.Contact, contacts)
  119. }
  120. w.Header().Set("Location", "https://ca.tld/acme/reg/1")
  121. w.Header().Set("Link", `<https://ca.tld/acme/new-authz>;rel="next"`)
  122. w.Header().Add("Link", `<https://ca.tld/acme/recover-reg>;rel="recover"`)
  123. w.Header().Add("Link", `<https://ca.tld/acme/terms>;rel="terms-of-service"`)
  124. w.WriteHeader(http.StatusCreated)
  125. b, _ := json.Marshal(contacts)
  126. fmt.Fprintf(w, `{"contact": %s}`, b)
  127. }))
  128. defer ts.Close()
  129. prompt := func(url string) bool {
  130. const terms = "https://ca.tld/acme/terms"
  131. if url != terms {
  132. t.Errorf("prompt url = %q; want %q", url, terms)
  133. }
  134. return false
  135. }
  136. c := Client{Key: testKeyEC, dir: &Directory{RegURL: ts.URL}}
  137. a := &Account{Contact: contacts}
  138. var err error
  139. if a, err = c.Register(context.Background(), a, prompt); err != nil {
  140. t.Fatal(err)
  141. }
  142. if a.URI != "https://ca.tld/acme/reg/1" {
  143. t.Errorf("a.URI = %q; want https://ca.tld/acme/reg/1", a.URI)
  144. }
  145. if a.Authz != "https://ca.tld/acme/new-authz" {
  146. t.Errorf("a.Authz = %q; want https://ca.tld/acme/new-authz", a.Authz)
  147. }
  148. if a.CurrentTerms != "https://ca.tld/acme/terms" {
  149. t.Errorf("a.CurrentTerms = %q; want https://ca.tld/acme/terms", a.CurrentTerms)
  150. }
  151. if !reflect.DeepEqual(a.Contact, contacts) {
  152. t.Errorf("a.Contact = %v; want %v", a.Contact, contacts)
  153. }
  154. }
  155. func TestUpdateReg(t *testing.T) {
  156. const terms = "https://ca.tld/acme/terms"
  157. contacts := []string{"mailto:admin@example.com"}
  158. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  159. if r.Method == "HEAD" {
  160. w.Header().Set("Replay-Nonce", "test-nonce")
  161. return
  162. }
  163. if r.Method != "POST" {
  164. t.Errorf("r.Method = %q; want POST", r.Method)
  165. }
  166. var j struct {
  167. Resource string
  168. Contact []string
  169. Agreement string
  170. }
  171. decodeJWSRequest(t, &j, r)
  172. // Test request
  173. if j.Resource != "reg" {
  174. t.Errorf("j.Resource = %q; want reg", j.Resource)
  175. }
  176. if j.Agreement != terms {
  177. t.Errorf("j.Agreement = %q; want %q", j.Agreement, terms)
  178. }
  179. if !reflect.DeepEqual(j.Contact, contacts) {
  180. t.Errorf("j.Contact = %v; want %v", j.Contact, contacts)
  181. }
  182. w.Header().Set("Link", `<https://ca.tld/acme/new-authz>;rel="next"`)
  183. w.Header().Add("Link", `<https://ca.tld/acme/recover-reg>;rel="recover"`)
  184. w.Header().Add("Link", fmt.Sprintf(`<%s>;rel="terms-of-service"`, terms))
  185. w.WriteHeader(http.StatusOK)
  186. b, _ := json.Marshal(contacts)
  187. fmt.Fprintf(w, `{"contact":%s, "agreement":%q}`, b, terms)
  188. }))
  189. defer ts.Close()
  190. c := Client{Key: testKeyEC}
  191. a := &Account{URI: ts.URL, Contact: contacts, AgreedTerms: terms}
  192. var err error
  193. if a, err = c.UpdateReg(context.Background(), a); err != nil {
  194. t.Fatal(err)
  195. }
  196. if a.Authz != "https://ca.tld/acme/new-authz" {
  197. t.Errorf("a.Authz = %q; want https://ca.tld/acme/new-authz", a.Authz)
  198. }
  199. if a.AgreedTerms != terms {
  200. t.Errorf("a.AgreedTerms = %q; want %q", a.AgreedTerms, terms)
  201. }
  202. if a.CurrentTerms != terms {
  203. t.Errorf("a.CurrentTerms = %q; want %q", a.CurrentTerms, terms)
  204. }
  205. if a.URI != ts.URL {
  206. t.Errorf("a.URI = %q; want %q", a.URI, ts.URL)
  207. }
  208. }
  209. func TestGetReg(t *testing.T) {
  210. const terms = "https://ca.tld/acme/terms"
  211. const newTerms = "https://ca.tld/acme/new-terms"
  212. contacts := []string{"mailto:admin@example.com"}
  213. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  214. if r.Method == "HEAD" {
  215. w.Header().Set("Replay-Nonce", "test-nonce")
  216. return
  217. }
  218. if r.Method != "POST" {
  219. t.Errorf("r.Method = %q; want POST", r.Method)
  220. }
  221. var j struct {
  222. Resource string
  223. Contact []string
  224. Agreement string
  225. }
  226. decodeJWSRequest(t, &j, r)
  227. // Test request
  228. if j.Resource != "reg" {
  229. t.Errorf("j.Resource = %q; want reg", j.Resource)
  230. }
  231. if len(j.Contact) != 0 {
  232. t.Errorf("j.Contact = %v", j.Contact)
  233. }
  234. if j.Agreement != "" {
  235. t.Errorf("j.Agreement = %q", j.Agreement)
  236. }
  237. w.Header().Set("Link", `<https://ca.tld/acme/new-authz>;rel="next"`)
  238. w.Header().Add("Link", `<https://ca.tld/acme/recover-reg>;rel="recover"`)
  239. w.Header().Add("Link", fmt.Sprintf(`<%s>;rel="terms-of-service"`, newTerms))
  240. w.WriteHeader(http.StatusOK)
  241. b, _ := json.Marshal(contacts)
  242. fmt.Fprintf(w, `{"contact":%s, "agreement":%q}`, b, terms)
  243. }))
  244. defer ts.Close()
  245. c := Client{Key: testKeyEC}
  246. a, err := c.GetReg(context.Background(), ts.URL)
  247. if err != nil {
  248. t.Fatal(err)
  249. }
  250. if a.Authz != "https://ca.tld/acme/new-authz" {
  251. t.Errorf("a.AuthzURL = %q; want https://ca.tld/acme/new-authz", a.Authz)
  252. }
  253. if a.AgreedTerms != terms {
  254. t.Errorf("a.AgreedTerms = %q; want %q", a.AgreedTerms, terms)
  255. }
  256. if a.CurrentTerms != newTerms {
  257. t.Errorf("a.CurrentTerms = %q; want %q", a.CurrentTerms, newTerms)
  258. }
  259. if a.URI != ts.URL {
  260. t.Errorf("a.URI = %q; want %q", a.URI, ts.URL)
  261. }
  262. }
  263. func TestAuthorize(t *testing.T) {
  264. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  265. if r.Method == "HEAD" {
  266. w.Header().Set("Replay-Nonce", "test-nonce")
  267. return
  268. }
  269. if r.Method != "POST" {
  270. t.Errorf("r.Method = %q; want POST", r.Method)
  271. }
  272. var j struct {
  273. Resource string
  274. Identifier struct {
  275. Type string
  276. Value string
  277. }
  278. }
  279. decodeJWSRequest(t, &j, r)
  280. // Test request
  281. if j.Resource != "new-authz" {
  282. t.Errorf("j.Resource = %q; want new-authz", j.Resource)
  283. }
  284. if j.Identifier.Type != "dns" {
  285. t.Errorf("j.Identifier.Type = %q; want dns", j.Identifier.Type)
  286. }
  287. if j.Identifier.Value != "example.com" {
  288. t.Errorf("j.Identifier.Value = %q; want example.com", j.Identifier.Value)
  289. }
  290. w.Header().Set("Location", "https://ca.tld/acme/auth/1")
  291. w.WriteHeader(http.StatusCreated)
  292. fmt.Fprintf(w, `{
  293. "identifier": {"type":"dns","value":"example.com"},
  294. "status":"pending",
  295. "challenges":[
  296. {
  297. "type":"http-01",
  298. "status":"pending",
  299. "uri":"https://ca.tld/acme/challenge/publickey/id1",
  300. "token":"token1"
  301. },
  302. {
  303. "type":"tls-sni-01",
  304. "status":"pending",
  305. "uri":"https://ca.tld/acme/challenge/publickey/id2",
  306. "token":"token2"
  307. }
  308. ],
  309. "combinations":[[0],[1]]}`)
  310. }))
  311. defer ts.Close()
  312. cl := Client{Key: testKeyEC, dir: &Directory{AuthzURL: ts.URL}}
  313. auth, err := cl.Authorize(context.Background(), "example.com")
  314. if err != nil {
  315. t.Fatal(err)
  316. }
  317. if auth.URI != "https://ca.tld/acme/auth/1" {
  318. t.Errorf("URI = %q; want https://ca.tld/acme/auth/1", auth.URI)
  319. }
  320. if auth.Status != "pending" {
  321. t.Errorf("Status = %q; want pending", auth.Status)
  322. }
  323. if auth.Identifier.Type != "dns" {
  324. t.Errorf("Identifier.Type = %q; want dns", auth.Identifier.Type)
  325. }
  326. if auth.Identifier.Value != "example.com" {
  327. t.Errorf("Identifier.Value = %q; want example.com", auth.Identifier.Value)
  328. }
  329. if n := len(auth.Challenges); n != 2 {
  330. t.Fatalf("len(auth.Challenges) = %d; want 2", n)
  331. }
  332. c := auth.Challenges[0]
  333. if c.Type != "http-01" {
  334. t.Errorf("c.Type = %q; want http-01", c.Type)
  335. }
  336. if c.URI != "https://ca.tld/acme/challenge/publickey/id1" {
  337. t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI)
  338. }
  339. if c.Token != "token1" {
  340. t.Errorf("c.Token = %q; want token1", c.Token)
  341. }
  342. c = auth.Challenges[1]
  343. if c.Type != "tls-sni-01" {
  344. t.Errorf("c.Type = %q; want tls-sni-01", c.Type)
  345. }
  346. if c.URI != "https://ca.tld/acme/challenge/publickey/id2" {
  347. t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id2", c.URI)
  348. }
  349. if c.Token != "token2" {
  350. t.Errorf("c.Token = %q; want token2", c.Token)
  351. }
  352. combs := [][]int{{0}, {1}}
  353. if !reflect.DeepEqual(auth.Combinations, combs) {
  354. t.Errorf("auth.Combinations: %+v\nwant: %+v\n", auth.Combinations, combs)
  355. }
  356. }
  357. func TestAuthorizeValid(t *testing.T) {
  358. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  359. if r.Method == "HEAD" {
  360. w.Header().Set("Replay-Nonce", "nonce")
  361. return
  362. }
  363. w.WriteHeader(http.StatusCreated)
  364. w.Write([]byte(`{"status":"valid"}`))
  365. }))
  366. defer ts.Close()
  367. client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}}
  368. _, err := client.Authorize(context.Background(), "example.com")
  369. if err != nil {
  370. t.Errorf("err = %v", err)
  371. }
  372. }
  373. func TestGetAuthorization(t *testing.T) {
  374. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  375. if r.Method != "GET" {
  376. t.Errorf("r.Method = %q; want GET", r.Method)
  377. }
  378. w.WriteHeader(http.StatusOK)
  379. fmt.Fprintf(w, `{
  380. "identifier": {"type":"dns","value":"example.com"},
  381. "status":"pending",
  382. "challenges":[
  383. {
  384. "type":"http-01",
  385. "status":"pending",
  386. "uri":"https://ca.tld/acme/challenge/publickey/id1",
  387. "token":"token1"
  388. },
  389. {
  390. "type":"tls-sni-01",
  391. "status":"pending",
  392. "uri":"https://ca.tld/acme/challenge/publickey/id2",
  393. "token":"token2"
  394. }
  395. ],
  396. "combinations":[[0],[1]]}`)
  397. }))
  398. defer ts.Close()
  399. cl := Client{Key: testKeyEC}
  400. auth, err := cl.GetAuthorization(context.Background(), ts.URL)
  401. if err != nil {
  402. t.Fatal(err)
  403. }
  404. if auth.Status != "pending" {
  405. t.Errorf("Status = %q; want pending", auth.Status)
  406. }
  407. if auth.Identifier.Type != "dns" {
  408. t.Errorf("Identifier.Type = %q; want dns", auth.Identifier.Type)
  409. }
  410. if auth.Identifier.Value != "example.com" {
  411. t.Errorf("Identifier.Value = %q; want example.com", auth.Identifier.Value)
  412. }
  413. if n := len(auth.Challenges); n != 2 {
  414. t.Fatalf("len(set.Challenges) = %d; want 2", n)
  415. }
  416. c := auth.Challenges[0]
  417. if c.Type != "http-01" {
  418. t.Errorf("c.Type = %q; want http-01", c.Type)
  419. }
  420. if c.URI != "https://ca.tld/acme/challenge/publickey/id1" {
  421. t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI)
  422. }
  423. if c.Token != "token1" {
  424. t.Errorf("c.Token = %q; want token1", c.Token)
  425. }
  426. c = auth.Challenges[1]
  427. if c.Type != "tls-sni-01" {
  428. t.Errorf("c.Type = %q; want tls-sni-01", c.Type)
  429. }
  430. if c.URI != "https://ca.tld/acme/challenge/publickey/id2" {
  431. t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id2", c.URI)
  432. }
  433. if c.Token != "token2" {
  434. t.Errorf("c.Token = %q; want token2", c.Token)
  435. }
  436. combs := [][]int{{0}, {1}}
  437. if !reflect.DeepEqual(auth.Combinations, combs) {
  438. t.Errorf("auth.Combinations: %+v\nwant: %+v\n", auth.Combinations, combs)
  439. }
  440. }
  441. func TestWaitAuthorization(t *testing.T) {
  442. t.Run("wait loop", func(t *testing.T) {
  443. var count int
  444. authz, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) {
  445. count++
  446. w.Header().Set("Retry-After", "0")
  447. if count > 1 {
  448. fmt.Fprintf(w, `{"status":"valid"}`)
  449. return
  450. }
  451. fmt.Fprintf(w, `{"status":"pending"}`)
  452. })
  453. if err != nil {
  454. t.Fatalf("non-nil error: %v", err)
  455. }
  456. if authz == nil {
  457. t.Fatal("authz is nil")
  458. }
  459. })
  460. t.Run("invalid status", func(t *testing.T) {
  461. _, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) {
  462. fmt.Fprintf(w, `{"status":"invalid"}`)
  463. })
  464. if _, ok := err.(*AuthorizationError); !ok {
  465. t.Errorf("err is %v (%T); want non-nil *AuthorizationError", err, err)
  466. }
  467. })
  468. t.Run("non-retriable error", func(t *testing.T) {
  469. const code = http.StatusBadRequest
  470. _, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) {
  471. w.WriteHeader(code)
  472. })
  473. res, ok := err.(*Error)
  474. if !ok {
  475. t.Fatalf("err is %v (%T); want a non-nil *Error", err, err)
  476. }
  477. if res.StatusCode != code {
  478. t.Errorf("res.StatusCode = %d; want %d", res.StatusCode, code)
  479. }
  480. })
  481. for _, code := range []int{http.StatusTooManyRequests, http.StatusInternalServerError} {
  482. t.Run(fmt.Sprintf("retriable %d error", code), func(t *testing.T) {
  483. var count int
  484. authz, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) {
  485. count++
  486. w.Header().Set("Retry-After", "0")
  487. if count > 1 {
  488. fmt.Fprintf(w, `{"status":"valid"}`)
  489. return
  490. }
  491. w.WriteHeader(code)
  492. })
  493. if err != nil {
  494. t.Fatalf("non-nil error: %v", err)
  495. }
  496. if authz == nil {
  497. t.Fatal("authz is nil")
  498. }
  499. })
  500. }
  501. t.Run("context cancel", func(t *testing.T) {
  502. ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
  503. defer cancel()
  504. _, err := runWaitAuthorization(ctx, t, func(w http.ResponseWriter, r *http.Request) {
  505. w.Header().Set("Retry-After", "60")
  506. fmt.Fprintf(w, `{"status":"pending"}`)
  507. })
  508. if err == nil {
  509. t.Error("err is nil")
  510. }
  511. })
  512. }
  513. func runWaitAuthorization(ctx context.Context, t *testing.T, h http.HandlerFunc) (*Authorization, error) {
  514. t.Helper()
  515. ts := httptest.NewServer(h)
  516. defer ts.Close()
  517. type res struct {
  518. authz *Authorization
  519. err error
  520. }
  521. ch := make(chan res, 1)
  522. go func() {
  523. var client Client
  524. a, err := client.WaitAuthorization(ctx, ts.URL)
  525. ch <- res{a, err}
  526. }()
  527. select {
  528. case <-time.After(3 * time.Second):
  529. t.Fatal("WaitAuthorization took too long to return")
  530. case v := <-ch:
  531. return v.authz, v.err
  532. }
  533. panic("runWaitAuthorization: out of select")
  534. }
  535. func TestRevokeAuthorization(t *testing.T) {
  536. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  537. if r.Method == "HEAD" {
  538. w.Header().Set("Replay-Nonce", "nonce")
  539. return
  540. }
  541. switch r.URL.Path {
  542. case "/1":
  543. var req struct {
  544. Resource string
  545. Status string
  546. Delete bool
  547. }
  548. decodeJWSRequest(t, &req, r)
  549. if req.Resource != "authz" {
  550. t.Errorf("req.Resource = %q; want authz", req.Resource)
  551. }
  552. if req.Status != "deactivated" {
  553. t.Errorf("req.Status = %q; want deactivated", req.Status)
  554. }
  555. if !req.Delete {
  556. t.Errorf("req.Delete is false")
  557. }
  558. case "/2":
  559. w.WriteHeader(http.StatusBadRequest)
  560. }
  561. }))
  562. defer ts.Close()
  563. client := &Client{Key: testKey}
  564. ctx := context.Background()
  565. if err := client.RevokeAuthorization(ctx, ts.URL+"/1"); err != nil {
  566. t.Errorf("err = %v", err)
  567. }
  568. if client.RevokeAuthorization(ctx, ts.URL+"/2") == nil {
  569. t.Error("nil error")
  570. }
  571. }
  572. func TestPollChallenge(t *testing.T) {
  573. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  574. if r.Method != "GET" {
  575. t.Errorf("r.Method = %q; want GET", r.Method)
  576. }
  577. w.WriteHeader(http.StatusOK)
  578. fmt.Fprintf(w, `{
  579. "type":"http-01",
  580. "status":"pending",
  581. "uri":"https://ca.tld/acme/challenge/publickey/id1",
  582. "token":"token1"}`)
  583. }))
  584. defer ts.Close()
  585. cl := Client{Key: testKeyEC}
  586. chall, err := cl.GetChallenge(context.Background(), ts.URL)
  587. if err != nil {
  588. t.Fatal(err)
  589. }
  590. if chall.Status != "pending" {
  591. t.Errorf("Status = %q; want pending", chall.Status)
  592. }
  593. if chall.Type != "http-01" {
  594. t.Errorf("c.Type = %q; want http-01", chall.Type)
  595. }
  596. if chall.URI != "https://ca.tld/acme/challenge/publickey/id1" {
  597. t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", chall.URI)
  598. }
  599. if chall.Token != "token1" {
  600. t.Errorf("c.Token = %q; want token1", chall.Token)
  601. }
  602. }
  603. func TestAcceptChallenge(t *testing.T) {
  604. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  605. if r.Method == "HEAD" {
  606. w.Header().Set("Replay-Nonce", "test-nonce")
  607. return
  608. }
  609. if r.Method != "POST" {
  610. t.Errorf("r.Method = %q; want POST", r.Method)
  611. }
  612. var j struct {
  613. Resource string
  614. Type string
  615. Auth string `json:"keyAuthorization"`
  616. }
  617. decodeJWSRequest(t, &j, r)
  618. // Test request
  619. if j.Resource != "challenge" {
  620. t.Errorf(`resource = %q; want "challenge"`, j.Resource)
  621. }
  622. if j.Type != "http-01" {
  623. t.Errorf(`type = %q; want "http-01"`, j.Type)
  624. }
  625. keyAuth := "token1." + testKeyECThumbprint
  626. if j.Auth != keyAuth {
  627. t.Errorf(`keyAuthorization = %q; want %q`, j.Auth, keyAuth)
  628. }
  629. // Respond to request
  630. w.WriteHeader(http.StatusAccepted)
  631. fmt.Fprintf(w, `{
  632. "type":"http-01",
  633. "status":"pending",
  634. "uri":"https://ca.tld/acme/challenge/publickey/id1",
  635. "token":"token1",
  636. "keyAuthorization":%q
  637. }`, keyAuth)
  638. }))
  639. defer ts.Close()
  640. cl := Client{Key: testKeyEC}
  641. c, err := cl.Accept(context.Background(), &Challenge{
  642. URI: ts.URL,
  643. Token: "token1",
  644. Type: "http-01",
  645. })
  646. if err != nil {
  647. t.Fatal(err)
  648. }
  649. if c.Type != "http-01" {
  650. t.Errorf("c.Type = %q; want http-01", c.Type)
  651. }
  652. if c.URI != "https://ca.tld/acme/challenge/publickey/id1" {
  653. t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI)
  654. }
  655. if c.Token != "token1" {
  656. t.Errorf("c.Token = %q; want token1", c.Token)
  657. }
  658. }
  659. func TestNewCert(t *testing.T) {
  660. notBefore := time.Now()
  661. notAfter := notBefore.AddDate(0, 2, 0)
  662. timeNow = func() time.Time { return notBefore }
  663. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  664. if r.Method == "HEAD" {
  665. w.Header().Set("Replay-Nonce", "test-nonce")
  666. return
  667. }
  668. if r.Method != "POST" {
  669. t.Errorf("r.Method = %q; want POST", r.Method)
  670. }
  671. var j struct {
  672. Resource string `json:"resource"`
  673. CSR string `json:"csr"`
  674. NotBefore string `json:"notBefore,omitempty"`
  675. NotAfter string `json:"notAfter,omitempty"`
  676. }
  677. decodeJWSRequest(t, &j, r)
  678. // Test request
  679. if j.Resource != "new-cert" {
  680. t.Errorf(`resource = %q; want "new-cert"`, j.Resource)
  681. }
  682. if j.NotBefore != notBefore.Format(time.RFC3339) {
  683. t.Errorf(`notBefore = %q; wanted %q`, j.NotBefore, notBefore.Format(time.RFC3339))
  684. }
  685. if j.NotAfter != notAfter.Format(time.RFC3339) {
  686. t.Errorf(`notAfter = %q; wanted %q`, j.NotAfter, notAfter.Format(time.RFC3339))
  687. }
  688. // Respond to request
  689. template := x509.Certificate{
  690. SerialNumber: big.NewInt(int64(1)),
  691. Subject: pkix.Name{
  692. Organization: []string{"goacme"},
  693. },
  694. NotBefore: notBefore,
  695. NotAfter: notAfter,
  696. KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
  697. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
  698. BasicConstraintsValid: true,
  699. }
  700. sampleCert, err := x509.CreateCertificate(rand.Reader, &template, &template, &testKeyEC.PublicKey, testKeyEC)
  701. if err != nil {
  702. t.Fatalf("Error creating certificate: %v", err)
  703. }
  704. w.Header().Set("Location", "https://ca.tld/acme/cert/1")
  705. w.WriteHeader(http.StatusCreated)
  706. w.Write(sampleCert)
  707. }))
  708. defer ts.Close()
  709. csr := x509.CertificateRequest{
  710. Version: 0,
  711. Subject: pkix.Name{
  712. CommonName: "example.com",
  713. Organization: []string{"goacme"},
  714. },
  715. }
  716. csrb, err := x509.CreateCertificateRequest(rand.Reader, &csr, testKeyEC)
  717. if err != nil {
  718. t.Fatal(err)
  719. }
  720. c := Client{Key: testKeyEC, dir: &Directory{CertURL: ts.URL}}
  721. cert, certURL, err := c.CreateCert(context.Background(), csrb, notAfter.Sub(notBefore), false)
  722. if err != nil {
  723. t.Fatal(err)
  724. }
  725. if cert == nil {
  726. t.Errorf("cert is nil")
  727. }
  728. if certURL != "https://ca.tld/acme/cert/1" {
  729. t.Errorf("certURL = %q; want https://ca.tld/acme/cert/1", certURL)
  730. }
  731. }
  732. func TestFetchCert(t *testing.T) {
  733. var count byte
  734. var ts *httptest.Server
  735. ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  736. count++
  737. if count < 3 {
  738. up := fmt.Sprintf("<%s>;rel=up", ts.URL)
  739. w.Header().Set("Link", up)
  740. }
  741. w.Write([]byte{count})
  742. }))
  743. defer ts.Close()
  744. res, err := (&Client{}).FetchCert(context.Background(), ts.URL, true)
  745. if err != nil {
  746. t.Fatalf("FetchCert: %v", err)
  747. }
  748. cert := [][]byte{{1}, {2}, {3}}
  749. if !reflect.DeepEqual(res, cert) {
  750. t.Errorf("res = %v; want %v", res, cert)
  751. }
  752. }
  753. func TestFetchCertRetry(t *testing.T) {
  754. var count int
  755. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  756. if count < 1 {
  757. w.Header().Set("Retry-After", "0")
  758. w.WriteHeader(http.StatusTooManyRequests)
  759. count++
  760. return
  761. }
  762. w.Write([]byte{1})
  763. }))
  764. defer ts.Close()
  765. res, err := (&Client{}).FetchCert(context.Background(), ts.URL, false)
  766. if err != nil {
  767. t.Fatalf("FetchCert: %v", err)
  768. }
  769. cert := [][]byte{{1}}
  770. if !reflect.DeepEqual(res, cert) {
  771. t.Errorf("res = %v; want %v", res, cert)
  772. }
  773. }
  774. func TestFetchCertCancel(t *testing.T) {
  775. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  776. w.Header().Set("Retry-After", "0")
  777. w.WriteHeader(http.StatusAccepted)
  778. }))
  779. defer ts.Close()
  780. ctx, cancel := context.WithCancel(context.Background())
  781. done := make(chan struct{})
  782. var err error
  783. go func() {
  784. _, err = (&Client{}).FetchCert(ctx, ts.URL, false)
  785. close(done)
  786. }()
  787. cancel()
  788. <-done
  789. if err != context.Canceled {
  790. t.Errorf("err = %v; want %v", err, context.Canceled)
  791. }
  792. }
  793. func TestFetchCertDepth(t *testing.T) {
  794. var count byte
  795. var ts *httptest.Server
  796. ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  797. count++
  798. if count > maxChainLen+1 {
  799. t.Errorf("count = %d; want at most %d", count, maxChainLen+1)
  800. w.WriteHeader(http.StatusInternalServerError)
  801. }
  802. w.Header().Set("Link", fmt.Sprintf("<%s>;rel=up", ts.URL))
  803. w.Write([]byte{count})
  804. }))
  805. defer ts.Close()
  806. _, err := (&Client{}).FetchCert(context.Background(), ts.URL, true)
  807. if err == nil {
  808. t.Errorf("err is nil")
  809. }
  810. }
  811. func TestFetchCertBreadth(t *testing.T) {
  812. var ts *httptest.Server
  813. ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  814. for i := 0; i < maxChainLen+1; i++ {
  815. w.Header().Add("Link", fmt.Sprintf("<%s>;rel=up", ts.URL))
  816. }
  817. w.Write([]byte{1})
  818. }))
  819. defer ts.Close()
  820. _, err := (&Client{}).FetchCert(context.Background(), ts.URL, true)
  821. if err == nil {
  822. t.Errorf("err is nil")
  823. }
  824. }
  825. func TestFetchCertSize(t *testing.T) {
  826. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  827. b := bytes.Repeat([]byte{1}, maxCertSize+1)
  828. w.Write(b)
  829. }))
  830. defer ts.Close()
  831. _, err := (&Client{}).FetchCert(context.Background(), ts.URL, false)
  832. if err == nil {
  833. t.Errorf("err is nil")
  834. }
  835. }
  836. func TestRevokeCert(t *testing.T) {
  837. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  838. if r.Method == "HEAD" {
  839. w.Header().Set("Replay-Nonce", "nonce")
  840. return
  841. }
  842. var req struct {
  843. Resource string
  844. Certificate string
  845. Reason int
  846. }
  847. decodeJWSRequest(t, &req, r)
  848. if req.Resource != "revoke-cert" {
  849. t.Errorf("req.Resource = %q; want revoke-cert", req.Resource)
  850. }
  851. if req.Reason != 1 {
  852. t.Errorf("req.Reason = %d; want 1", req.Reason)
  853. }
  854. // echo -n cert | base64 | tr -d '=' | tr '/+' '_-'
  855. cert := "Y2VydA"
  856. if req.Certificate != cert {
  857. t.Errorf("req.Certificate = %q; want %q", req.Certificate, cert)
  858. }
  859. }))
  860. defer ts.Close()
  861. client := &Client{
  862. Key: testKeyEC,
  863. dir: &Directory{RevokeURL: ts.URL},
  864. }
  865. ctx := context.Background()
  866. if err := client.RevokeCert(ctx, nil, []byte("cert"), CRLReasonKeyCompromise); err != nil {
  867. t.Fatal(err)
  868. }
  869. }
  870. func TestNonce_add(t *testing.T) {
  871. var c Client
  872. c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
  873. c.addNonce(http.Header{"Replay-Nonce": {}})
  874. c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
  875. nonces := map[string]struct{}{"nonce": {}}
  876. if !reflect.DeepEqual(c.nonces, nonces) {
  877. t.Errorf("c.nonces = %q; want %q", c.nonces, nonces)
  878. }
  879. }
  880. func TestNonce_addMax(t *testing.T) {
  881. c := &Client{nonces: make(map[string]struct{})}
  882. for i := 0; i < maxNonces; i++ {
  883. c.nonces[fmt.Sprintf("%d", i)] = struct{}{}
  884. }
  885. c.addNonce(http.Header{"Replay-Nonce": {"nonce"}})
  886. if n := len(c.nonces); n != maxNonces {
  887. t.Errorf("len(c.nonces) = %d; want %d", n, maxNonces)
  888. }
  889. }
  890. func TestNonce_fetch(t *testing.T) {
  891. tests := []struct {
  892. code int
  893. nonce string
  894. }{
  895. {http.StatusOK, "nonce1"},
  896. {http.StatusBadRequest, "nonce2"},
  897. {http.StatusOK, ""},
  898. }
  899. var i int
  900. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  901. if r.Method != "HEAD" {
  902. t.Errorf("%d: r.Method = %q; want HEAD", i, r.Method)
  903. }
  904. w.Header().Set("Replay-Nonce", tests[i].nonce)
  905. w.WriteHeader(tests[i].code)
  906. }))
  907. defer ts.Close()
  908. for ; i < len(tests); i++ {
  909. test := tests[i]
  910. c := &Client{}
  911. n, err := c.fetchNonce(context.Background(), ts.URL)
  912. if n != test.nonce {
  913. t.Errorf("%d: n=%q; want %q", i, n, test.nonce)
  914. }
  915. switch {
  916. case err == nil && test.nonce == "":
  917. t.Errorf("%d: n=%q, err=%v; want non-nil error", i, n, err)
  918. case err != nil && test.nonce != "":
  919. t.Errorf("%d: n=%q, err=%v; want %q", i, n, err, test.nonce)
  920. }
  921. }
  922. }
  923. func TestNonce_fetchError(t *testing.T) {
  924. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  925. w.WriteHeader(http.StatusTooManyRequests)
  926. }))
  927. defer ts.Close()
  928. c := &Client{}
  929. _, err := c.fetchNonce(context.Background(), ts.URL)
  930. e, ok := err.(*Error)
  931. if !ok {
  932. t.Fatalf("err is %T; want *Error", err)
  933. }
  934. if e.StatusCode != http.StatusTooManyRequests {
  935. t.Errorf("e.StatusCode = %d; want %d", e.StatusCode, http.StatusTooManyRequests)
  936. }
  937. }
  938. func TestNonce_postJWS(t *testing.T) {
  939. var count int
  940. seen := make(map[string]bool)
  941. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  942. count++
  943. w.Header().Set("Replay-Nonce", fmt.Sprintf("nonce%d", count))
  944. if r.Method == "HEAD" {
  945. // We expect the client do a HEAD request
  946. // but only to fetch the first nonce.
  947. return
  948. }
  949. // Make client.Authorize happy; we're not testing its result.
  950. defer func() {
  951. w.WriteHeader(http.StatusCreated)
  952. w.Write([]byte(`{"status":"valid"}`))
  953. }()
  954. head, err := decodeJWSHead(r)
  955. if err != nil {
  956. t.Errorf("decodeJWSHead: %v", err)
  957. return
  958. }
  959. if head.Nonce == "" {
  960. t.Error("head.Nonce is empty")
  961. return
  962. }
  963. if seen[head.Nonce] {
  964. t.Errorf("nonce is already used: %q", head.Nonce)
  965. }
  966. seen[head.Nonce] = true
  967. }))
  968. defer ts.Close()
  969. client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}}
  970. if _, err := client.Authorize(context.Background(), "example.com"); err != nil {
  971. t.Errorf("client.Authorize 1: %v", err)
  972. }
  973. // The second call should not generate another extra HEAD request.
  974. if _, err := client.Authorize(context.Background(), "example.com"); err != nil {
  975. t.Errorf("client.Authorize 2: %v", err)
  976. }
  977. if count != 3 {
  978. t.Errorf("total requests count: %d; want 3", count)
  979. }
  980. if n := len(client.nonces); n != 1 {
  981. t.Errorf("len(client.nonces) = %d; want 1", n)
  982. }
  983. for k := range seen {
  984. if _, exist := client.nonces[k]; exist {
  985. t.Errorf("used nonce %q in client.nonces", k)
  986. }
  987. }
  988. }
  989. func TestLinkHeader(t *testing.T) {
  990. h := http.Header{"Link": {
  991. `<https://example.com/acme/new-authz>;rel="next"`,
  992. `<https://example.com/acme/recover-reg>; rel=recover`,
  993. `<https://example.com/acme/terms>; foo=bar; rel="terms-of-service"`,
  994. `<dup>;rel="next"`,
  995. }}
  996. tests := []struct {
  997. rel string
  998. out []string
  999. }{
  1000. {"next", []string{"https://example.com/acme/new-authz", "dup"}},
  1001. {"recover", []string{"https://example.com/acme/recover-reg"}},
  1002. {"terms-of-service", []string{"https://example.com/acme/terms"}},
  1003. {"empty", nil},
  1004. }
  1005. for i, test := range tests {
  1006. if v := linkHeader(h, test.rel); !reflect.DeepEqual(v, test.out) {
  1007. t.Errorf("%d: linkHeader(%q): %v; want %v", i, test.rel, v, test.out)
  1008. }
  1009. }
  1010. }
  1011. func TestTLSSNI01ChallengeCert(t *testing.T) {
  1012. const (
  1013. token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA"
  1014. // echo -n <token.testKeyECThumbprint> | shasum -a 256
  1015. san = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.acme.invalid"
  1016. )
  1017. client := &Client{Key: testKeyEC}
  1018. tlscert, name, err := client.TLSSNI01ChallengeCert(token)
  1019. if err != nil {
  1020. t.Fatal(err)
  1021. }
  1022. if n := len(tlscert.Certificate); n != 1 {
  1023. t.Fatalf("len(tlscert.Certificate) = %d; want 1", n)
  1024. }
  1025. cert, err := x509.ParseCertificate(tlscert.Certificate[0])
  1026. if err != nil {
  1027. t.Fatal(err)
  1028. }
  1029. if len(cert.DNSNames) != 1 || cert.DNSNames[0] != san {
  1030. t.Fatalf("cert.DNSNames = %v; want %q", cert.DNSNames, san)
  1031. }
  1032. if cert.DNSNames[0] != name {
  1033. t.Errorf("cert.DNSNames[0] != name: %q vs %q", cert.DNSNames[0], name)
  1034. }
  1035. if cn := cert.Subject.CommonName; cn != san {
  1036. t.Errorf("cert.Subject.CommonName = %q; want %q", cn, san)
  1037. }
  1038. }
  1039. func TestTLSSNI02ChallengeCert(t *testing.T) {
  1040. const (
  1041. token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA"
  1042. // echo -n evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA | shasum -a 256
  1043. sanA = "7ea0aaa69214e71e02cebb18bb867736.09b730209baabf60e43d4999979ff139.token.acme.invalid"
  1044. // echo -n <token.testKeyECThumbprint> | shasum -a 256
  1045. sanB = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.ka.acme.invalid"
  1046. )
  1047. client := &Client{Key: testKeyEC}
  1048. tlscert, name, err := client.TLSSNI02ChallengeCert(token)
  1049. if err != nil {
  1050. t.Fatal(err)
  1051. }
  1052. if n := len(tlscert.Certificate); n != 1 {
  1053. t.Fatalf("len(tlscert.Certificate) = %d; want 1", n)
  1054. }
  1055. cert, err := x509.ParseCertificate(tlscert.Certificate[0])
  1056. if err != nil {
  1057. t.Fatal(err)
  1058. }
  1059. names := []string{sanA, sanB}
  1060. if !reflect.DeepEqual(cert.DNSNames, names) {
  1061. t.Fatalf("cert.DNSNames = %v;\nwant %v", cert.DNSNames, names)
  1062. }
  1063. sort.Strings(cert.DNSNames)
  1064. i := sort.SearchStrings(cert.DNSNames, name)
  1065. if i >= len(cert.DNSNames) || cert.DNSNames[i] != name {
  1066. t.Errorf("%v doesn't have %q", cert.DNSNames, name)
  1067. }
  1068. if cn := cert.Subject.CommonName; cn != sanA {
  1069. t.Errorf("CommonName = %q; want %q", cn, sanA)
  1070. }
  1071. }
  1072. func TestTLSChallengeCertOpt(t *testing.T) {
  1073. key, err := rsa.GenerateKey(rand.Reader, 512)
  1074. if err != nil {
  1075. t.Fatal(err)
  1076. }
  1077. tmpl := &x509.Certificate{
  1078. SerialNumber: big.NewInt(2),
  1079. Subject: pkix.Name{Organization: []string{"Test"}},
  1080. DNSNames: []string{"should-be-overwritten"},
  1081. }
  1082. opts := []CertOption{WithKey(key), WithTemplate(tmpl)}
  1083. client := &Client{Key: testKeyEC}
  1084. cert1, _, err := client.TLSSNI01ChallengeCert("token", opts...)
  1085. if err != nil {
  1086. t.Fatal(err)
  1087. }
  1088. cert2, _, err := client.TLSSNI02ChallengeCert("token", opts...)
  1089. if err != nil {
  1090. t.Fatal(err)
  1091. }
  1092. for i, tlscert := range []tls.Certificate{cert1, cert2} {
  1093. // verify generated cert private key
  1094. tlskey, ok := tlscert.PrivateKey.(*rsa.PrivateKey)
  1095. if !ok {
  1096. t.Errorf("%d: tlscert.PrivateKey is %T; want *rsa.PrivateKey", i, tlscert.PrivateKey)
  1097. continue
  1098. }
  1099. if tlskey.D.Cmp(key.D) != 0 {
  1100. t.Errorf("%d: tlskey.D = %v; want %v", i, tlskey.D, key.D)
  1101. }
  1102. // verify generated cert public key
  1103. x509Cert, err := x509.ParseCertificate(tlscert.Certificate[0])
  1104. if err != nil {
  1105. t.Errorf("%d: %v", i, err)
  1106. continue
  1107. }
  1108. tlspub, ok := x509Cert.PublicKey.(*rsa.PublicKey)
  1109. if !ok {
  1110. t.Errorf("%d: x509Cert.PublicKey is %T; want *rsa.PublicKey", i, x509Cert.PublicKey)
  1111. continue
  1112. }
  1113. if tlspub.N.Cmp(key.N) != 0 {
  1114. t.Errorf("%d: tlspub.N = %v; want %v", i, tlspub.N, key.N)
  1115. }
  1116. // verify template option
  1117. sn := big.NewInt(2)
  1118. if x509Cert.SerialNumber.Cmp(sn) != 0 {
  1119. t.Errorf("%d: SerialNumber = %v; want %v", i, x509Cert.SerialNumber, sn)
  1120. }
  1121. org := []string{"Test"}
  1122. if !reflect.DeepEqual(x509Cert.Subject.Organization, org) {
  1123. t.Errorf("%d: Subject.Organization = %+v; want %+v", i, x509Cert.Subject.Organization, org)
  1124. }
  1125. for _, v := range x509Cert.DNSNames {
  1126. if !strings.HasSuffix(v, ".acme.invalid") {
  1127. t.Errorf("%d: invalid DNSNames element: %q", i, v)
  1128. }
  1129. }
  1130. }
  1131. }
  1132. func TestHTTP01Challenge(t *testing.T) {
  1133. const (
  1134. token = "xxx"
  1135. // thumbprint is precomputed for testKeyEC in jws_test.go
  1136. value = token + "." + testKeyECThumbprint
  1137. urlpath = "/.well-known/acme-challenge/" + token
  1138. )
  1139. client := &Client{Key: testKeyEC}
  1140. val, err := client.HTTP01ChallengeResponse(token)
  1141. if err != nil {
  1142. t.Fatal(err)
  1143. }
  1144. if val != value {
  1145. t.Errorf("val = %q; want %q", val, value)
  1146. }
  1147. if path := client.HTTP01ChallengePath(token); path != urlpath {
  1148. t.Errorf("path = %q; want %q", path, urlpath)
  1149. }
  1150. }
  1151. func TestDNS01ChallengeRecord(t *testing.T) {
  1152. // echo -n xxx.<testKeyECThumbprint> | \
  1153. // openssl dgst -binary -sha256 | \
  1154. // base64 | tr -d '=' | tr '/+' '_-'
  1155. const value = "8DERMexQ5VcdJ_prpPiA0mVdp7imgbCgjsG4SqqNMIo"
  1156. client := &Client{Key: testKeyEC}
  1157. val, err := client.DNS01ChallengeRecord("xxx")
  1158. if err != nil {
  1159. t.Fatal(err)
  1160. }
  1161. if val != value {
  1162. t.Errorf("val = %q; want %q", val, value)
  1163. }
  1164. }