acme_test.go 36 KB

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