diff --git a/acme/api/certificate_test.go b/acme/api/certificate_test.go index 4ff8fec47..f9e92dc6c 100644 --- a/acme/api/certificate_test.go +++ b/acme/api/certificate_test.go @@ -3,7 +3,6 @@ package api import ( "crypto/rand" "crypto/rsa" - "net/http" "testing" "github.com/go-acme/lego/v4/platform/tester" @@ -74,14 +73,14 @@ rzFL1KZfz+HZdnFwFW2T2gVW8L3ii1l9AJDuKzlvjUH3p6bgihVq02sjT8mx+GM2 ` func TestCertificateService_Get_issuerRelUp(t *testing.T) { - apiURL := tester.MockACMEServer(). + apiURL, client := tester.MockACMEServer(). Route("POST /certificate", servermock.RawStringResponse(certResponseMock)). - Build(t) + BuildHTTPS(t) key, err := rsa.GenerateKey(rand.Reader, 2048) require.NoError(t, err, "Could not generate test key") - core, err := New(http.DefaultClient, "lego-test", apiURL+"/dir", "", key) + core, err := New(client, "lego-test", apiURL+"/dir", "", key) require.NoError(t, err) cert, issuer, err := core.Certificates.Get(apiURL+"/certificate", true) @@ -91,14 +90,14 @@ func TestCertificateService_Get_issuerRelUp(t *testing.T) { } func TestCertificateService_Get_embeddedIssuer(t *testing.T) { - apiURL := tester.MockACMEServer(). + apiURL, client := tester.MockACMEServer(). Route("POST /certificate", servermock.RawStringResponse(certResponseMock)). - Build(t) + BuildHTTPS(t) key, err := rsa.GenerateKey(rand.Reader, 2048) require.NoError(t, err, "Could not generate test key") - core, err := New(http.DefaultClient, "lego-test", apiURL+"/dir", "", key) + core, err := New(client, "lego-test", apiURL+"/dir", "", key) require.NoError(t, err) cert, issuer, err := core.Certificates.Get(apiURL+"/certificate", true) diff --git a/acme/api/internal/nonces/nonce_manager_test.go b/acme/api/internal/nonces/nonce_manager_test.go index a172a0b69..097e57587 100644 --- a/acme/api/internal/nonces/nonce_manager_test.go +++ b/acme/api/internal/nonces/nonce_manager_test.go @@ -8,35 +8,37 @@ import ( "github.com/go-acme/lego/v4/acme" "github.com/go-acme/lego/v4/acme/api/internal/sender" - "github.com/go-acme/lego/v4/platform/tester" + "github.com/go-acme/lego/v4/platform/tester/servermock" ) func TestNotHoldingLockWhileMakingHTTPRequests(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - time.Sleep(250 * time.Millisecond) - w.Header().Set("Replay-Nonce", "12345") - w.Header().Set("Retry-After", "0") - err := tester.WriteJSONResponse(w, &acme.Challenge{Type: "http-01", Status: "Valid", URL: "http://example.com/", Token: "token"}) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - })) - t.Cleanup(server.Close) + manager, _ := servermock.NewBuilder( + func(server *httptest.Server) (*Manager, error) { + doer := sender.NewDoer(server.Client(), "lego-test") + + return NewManager(doer, server.URL), nil + }). + Route("HEAD /", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + time.Sleep(250 * time.Millisecond) + + rw.Header().Set("Replay-Nonce", "12345") + rw.Header().Set("Retry-After", "0") + + servermock.JSONEncode(&acme.Challenge{Type: "http-01", Status: "Valid", URL: "https://example.com/", Token: "token"}).ServeHTTP(rw, req) + })). + BuildHTTPS(t) - doer := sender.NewDoer(http.DefaultClient, "lego-test") - j := NewManager(doer, server.URL) ch := make(chan bool) resultCh := make(chan bool) go func() { - _, errN := j.Nonce() + _, errN := manager.Nonce() if errN != nil { t.Log(errN) } ch <- true }() go func() { - _, errN := j.Nonce() + _, errN := manager.Nonce() if errN != nil { t.Log(errN) } diff --git a/acme/api/internal/secure/jws_test.go b/acme/api/internal/secure/jws_test.go index 2e625f24f..07761fb5e 100644 --- a/acme/api/internal/secure/jws_test.go +++ b/acme/api/internal/secure/jws_test.go @@ -9,35 +9,37 @@ import ( "github.com/go-acme/lego/v4/acme" "github.com/go-acme/lego/v4/acme/api/internal/nonces" "github.com/go-acme/lego/v4/acme/api/internal/sender" - "github.com/go-acme/lego/v4/platform/tester" + "github.com/go-acme/lego/v4/platform/tester/servermock" ) func TestNotHoldingLockWhileMakingHTTPRequests(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - time.Sleep(250 * time.Millisecond) - w.Header().Set("Replay-Nonce", "12345") - w.Header().Set("Retry-After", "0") - err := tester.WriteJSONResponse(w, &acme.Challenge{Type: "http-01", Status: "Valid", URL: "http://example.com/", Token: "token"}) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - })) - t.Cleanup(server.Close) + manager, _ := servermock.NewBuilder( + func(server *httptest.Server) (*nonces.Manager, error) { + doer := sender.NewDoer(server.Client(), "lego-test") + + return nonces.NewManager(doer, server.URL), nil + }). + Route("HEAD /", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + time.Sleep(250 * time.Millisecond) + + rw.Header().Set("Replay-Nonce", "12345") + rw.Header().Set("Retry-After", "0") + + servermock.JSONEncode(&acme.Challenge{Type: "http-01", Status: "Valid", URL: "https://example.com/", Token: "token"}).ServeHTTP(rw, req) + })). + BuildHTTPS(t) - doer := sender.NewDoer(http.DefaultClient, "lego-test") - j := nonces.NewManager(doer, server.URL) ch := make(chan bool) resultCh := make(chan bool) go func() { - _, errN := j.Nonce() + _, errN := manager.Nonce() if errN != nil { t.Log(errN) } ch <- true }() go func() { - _, errN := j.Nonce() + _, errN := manager.Nonce() if errN != nil { t.Log(errN) } diff --git a/acme/api/internal/sender/sender.go b/acme/api/internal/sender/sender.go index 2e1bbec8d..e70a4bd9c 100644 --- a/acme/api/internal/sender/sender.go +++ b/acme/api/internal/sender/sender.go @@ -27,6 +27,8 @@ type Doer struct { // NewDoer Creates a new Doer. func NewDoer(client *http.Client, userAgent string) *Doer { + client.Transport = newHTTPSOnly(client) + return &Doer{ httpClient: client, userAgent: userAgent, @@ -150,3 +152,28 @@ func checkError(req *http.Request, resp *http.Response) error { } return nil } + +type httpsOnly struct { + rt http.RoundTripper +} + +func newHTTPSOnly(client *http.Client) *httpsOnly { + if client.Transport == nil { + return &httpsOnly{rt: http.DefaultTransport} + } + + return &httpsOnly{rt: client.Transport} +} + +// RoundTrip ensure HTTPS is used. +// Each ACME function is accomplished by the client sending a sequence of HTTPS requests to the server [RFC2818], +// carrying JSON messages [RFC8259]. +// Use of HTTPS is REQUIRED. +// https://datatracker.ietf.org/doc/html/rfc8555#section-6.1 +func (r *httpsOnly) RoundTrip(req *http.Request) (*http.Response, error) { + if req.URL.Scheme != "https" { + return nil, fmt.Errorf("HTTPS is required: %s", req.URL) + } + + return r.rt.RoundTrip(req) +} diff --git a/acme/api/internal/sender/sender_test.go b/acme/api/internal/sender/sender_test.go index 2fd43c878..69bb8ae4e 100644 --- a/acme/api/internal/sender/sender_test.go +++ b/acme/api/internal/sender/sender_test.go @@ -12,13 +12,13 @@ import ( func TestDo_UserAgentOnAllHTTPMethod(t *testing.T) { var ua, method string - server := httptest.NewServer(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { + server := httptest.NewTLSServer(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { ua = r.Header.Get("User-Agent") method = r.Method })) t.Cleanup(server.Close) - doer := NewDoer(http.DefaultClient, "") + doer := NewDoer(server.Client(), "") testCases := []struct { method string @@ -65,3 +65,13 @@ func TestDo_CustomUserAgent(t *testing.T) { } assert.Len(t, strings.Split(ua, " "), 5) } + +func TestDo_failWithHTTP(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {})) + t.Cleanup(server.Close) + + sender := NewDoer(server.Client(), "test") + + _, err := sender.Post(server.URL, strings.NewReader("data"), "text/plain", nil) + require.ErrorContains(t, err, "HTTPS is required: http://") +} diff --git a/acme/api/order_test.go b/acme/api/order_test.go index ebbb7d7ce..da98f4714 100644 --- a/acme/api/order_test.go +++ b/acme/api/order_test.go @@ -22,7 +22,7 @@ func TestOrderService_NewWithOptions(t *testing.T) { privateKey, errK := rsa.GenerateKey(rand.Reader, 1024) require.NoError(t, errK, "Could not generate test key") - apiURL := tester.MockACMEServer(). + apiURL, client := tester.MockACMEServer(). Route("POST /newOrder", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { body, err := readSignedBody(req, privateKey) @@ -52,9 +52,9 @@ func TestOrderService_NewWithOptions(t *testing.T) { Replaces: order.Replaces, }).ServeHTTP(rw, req) })). - Build(t) + BuildHTTPS(t) - core, err := New(http.DefaultClient, "lego-test", apiURL+"/dir", "", privateKey) + core, err := New(client, "lego-test", apiURL+"/dir", "", privateKey) require.NoError(t, err) testCases := []struct { diff --git a/certificate/certificates_test.go b/certificate/certificates_test.go index ddccd3541..a016e3b6b 100644 --- a/certificate/certificates_test.go +++ b/certificate/certificates_test.go @@ -175,14 +175,14 @@ Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ ` func Test_checkResponse(t *testing.T) { - apiURL := tester.MockACMEServer(). + apiURL, client := tester.MockACMEServer(). Route("POST /certificate", servermock.RawStringResponse(certResponseMock)). - Build(t) + BuildHTTPS(t) key, err := rsa.GenerateKey(rand.Reader, 2048) require.NoError(t, err, "Could not generate test key") - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", key) + core, err := api.New(client, "lego-test", apiURL+"/dir", "", key) require.NoError(t, err) certifier := NewCertifier(core, &resolverMock{}, CertifierOptions{KeyType: certcrypto.RSA2048}) @@ -209,14 +209,14 @@ func Test_checkResponse(t *testing.T) { } func Test_checkResponse_issuerRelUp(t *testing.T) { - apiURL := tester.MockACMEServer(). + apiURL, client := tester.MockACMEServer(). Route("POST /certificate", servermock.RawStringResponse(certResponseMock)). - Build(t) + BuildHTTPS(t) key, err := rsa.GenerateKey(rand.Reader, 2048) require.NoError(t, err, "Could not generate test key") - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", key) + core, err := api.New(client, "lego-test", apiURL+"/dir", "", key) require.NoError(t, err) certifier := NewCertifier(core, &resolverMock{}, CertifierOptions{KeyType: certcrypto.RSA2048}) @@ -243,14 +243,14 @@ func Test_checkResponse_issuerRelUp(t *testing.T) { } func Test_checkResponse_no_bundle(t *testing.T) { - apiURL := tester.MockACMEServer(). + apiURL, client := tester.MockACMEServer(). Route("POST /certificate", servermock.RawStringResponse(certResponseMock)). - Build(t) + BuildHTTPS(t) key, err := rsa.GenerateKey(rand.Reader, 2048) require.NoError(t, err, "Could not generate test key") - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", key) + core, err := api.New(client, "lego-test", apiURL+"/dir", "", key) require.NoError(t, err) certifier := NewCertifier(core, &resolverMock{}, CertifierOptions{KeyType: certcrypto.RSA2048}) @@ -277,21 +277,21 @@ func Test_checkResponse_no_bundle(t *testing.T) { } func Test_checkResponse_alternate(t *testing.T) { - apiURL := tester.MockACMEServer(). + apiURL, client := tester.MockACMEServer(). Route("POST /certificate", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { rw.Header().Add("Link", - fmt.Sprintf(`;title="foo";rel="alternate"`, req.Context().Value(http.LocalAddrContextKey))) + fmt.Sprintf(`;title="foo";rel="alternate"`, req.Context().Value(http.LocalAddrContextKey))) servermock.RawStringResponse(certResponseMock).ServeHTTP(rw, req) })). Route("/certificate/1", servermock.RawStringResponse(certResponseMock2)). - Build(t) + BuildHTTPS(t) key, err := rsa.GenerateKey(rand.Reader, 2048) require.NoError(t, err, "Could not generate test key") - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", key) + core, err := api.New(client, "lego-test", apiURL+"/dir", "", key) require.NoError(t, err) certifier := NewCertifier(core, &resolverMock{}, CertifierOptions{KeyType: certcrypto.RSA2048}) @@ -321,14 +321,14 @@ func Test_checkResponse_alternate(t *testing.T) { } func Test_Get(t *testing.T) { - apiURL := tester.MockACMEServer(). + apiURL, client := tester.MockACMEServer(). Route("POST /acme/cert/test-cert", servermock.RawStringResponse(certResponseMock)). - Build(t) + BuildHTTPS(t) key, err := rsa.GenerateKey(rand.Reader, 2048) require.NoError(t, err, "Could not generate test key") - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", key) + core, err := api.New(client, "lego-test", apiURL+"/dir", "", key) require.NoError(t, err) certifier := NewCertifier(core, &resolverMock{}, CertifierOptions{KeyType: certcrypto.RSA2048}) diff --git a/certificate/renewal_test.go b/certificate/renewal_test.go index 9cf478600..7280f839f 100644 --- a/certificate/renewal_test.go +++ b/certificate/renewal_test.go @@ -43,7 +43,7 @@ func TestCertifier_GetRenewalInfo(t *testing.T) { require.NoError(t, err) // Test with a fake API. - apiURL := tester.MockACMEServer(). + apiURL, client := tester.MockACMEServer(). Route("GET /renewalInfo/"+ariLeafCertID, servermock.RawStringResponse(`{ "suggestedWindow": { @@ -55,12 +55,12 @@ func TestCertifier_GetRenewalInfo(t *testing.T) { }`). WithHeader("Content-Type", "application/json"). WithHeader("Retry-After", "21600")). - Build(t) + BuildHTTPS(t) key, err := rsa.GenerateKey(rand.Reader, 2048) require.NoError(t, err, "Could not generate test key") - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", key) + core, err := api.New(client, "lego-test", apiURL+"/dir", "", key) require.NoError(t, err) certifier := NewCertifier(core, &resolverMock{}, CertifierOptions{KeyType: certcrypto.RSA2048}) @@ -82,24 +82,23 @@ func TestCertifier_GetRenewalInfo_errors(t *testing.T) { require.NoError(t, err, "Could not generate test key") testCases := []struct { - desc string - httpClient *http.Client - request RenewalInfoRequest - handler http.HandlerFunc + desc string + timeout time.Duration + request RenewalInfoRequest + handler http.HandlerFunc }{ { - desc: "API timeout", - httpClient: &http.Client{Timeout: 500 * time.Millisecond}, // HTTP client that times out after 500ms. - request: RenewalInfoRequest{leaf}, + desc: "API timeout", + timeout: 500 * time.Millisecond, // HTTP client that times out after 500ms. + request: RenewalInfoRequest{leaf}, handler: func(w http.ResponseWriter, r *http.Request) { // API that takes 2ms to respond. time.Sleep(2 * time.Millisecond) }, }, { - desc: "API error", - httpClient: http.DefaultClient, - request: RenewalInfoRequest{leaf}, + desc: "API error", + request: RenewalInfoRequest{leaf}, handler: func(w http.ResponseWriter, r *http.Request) { // API that responds with error instead of renewal info. http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) @@ -111,11 +110,15 @@ func TestCertifier_GetRenewalInfo_errors(t *testing.T) { t.Run(test.desc, func(t *testing.T) { t.Parallel() - apiURL := tester.MockACMEServer(). + apiURL, client := tester.MockACMEServer(). Route("GET /renewalInfo/"+ariLeafCertID, test.handler). - Build(t) + BuildHTTPS(t) - core, err := api.New(test.httpClient, "lego-test", apiURL+"/dir", "", key) + if test.timeout != 0 { + client.Timeout = test.timeout + } + + core, err := api.New(client, "lego-test", apiURL+"/dir", "", key) require.NoError(t, err) certifier := NewCertifier(core, &resolverMock{}, CertifierOptions{KeyType: certcrypto.RSA2048}) diff --git a/challenge/dns01/dns_challenge_test.go b/challenge/dns01/dns_challenge_test.go index bb0564a81..6bc88ca23 100644 --- a/challenge/dns01/dns_challenge_test.go +++ b/challenge/dns01/dns_challenge_test.go @@ -4,7 +4,6 @@ import ( "crypto/rand" "crypto/rsa" "errors" - "net/http" "testing" "time" @@ -32,12 +31,12 @@ func (p *providerTimeoutMock) CleanUp(domain, token, keyAuth string) error { ret func (p *providerTimeoutMock) Timeout() (time.Duration, time.Duration) { return p.timeout, p.interval } func TestChallenge_PreSolve(t *testing.T) { - apiURL := tester.MockACMEServer().Build(t) + apiURL, client := tester.MockACMEServer().BuildHTTPS(t) privateKey, err := rsa.GenerateKey(rand.Reader, 1024) require.NoError(t, err) - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", privateKey) + core, err := api.New(client, "lego-test", apiURL+"/dir", "", privateKey) require.NoError(t, err) testCases := []struct { @@ -114,12 +113,12 @@ func TestChallenge_PreSolve(t *testing.T) { } func TestChallenge_Solve(t *testing.T) { - apiURL := tester.MockACMEServer().Build(t) + apiURL, client := tester.MockACMEServer().BuildHTTPS(t) privateKey, err := rsa.GenerateKey(rand.Reader, 1024) require.NoError(t, err) - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", privateKey) + core, err := api.New(client, "lego-test", apiURL+"/dir", "", privateKey) require.NoError(t, err) testCases := []struct { @@ -201,12 +200,12 @@ func TestChallenge_Solve(t *testing.T) { } func TestChallenge_CleanUp(t *testing.T) { - apiURL := tester.MockACMEServer().Build(t) + apiURL, client := tester.MockACMEServer().BuildHTTPS(t) privateKey, err := rsa.GenerateKey(rand.Reader, 1024) require.NoError(t, err) - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", privateKey) + core, err := api.New(client, "lego-test", apiURL+"/dir", "", privateKey) require.NoError(t, err) testCases := []struct { diff --git a/challenge/http01/http_challenge_test.go b/challenge/http01/http_challenge_test.go index a5e9cc62f..4693a7f47 100644 --- a/challenge/http01/http_challenge_test.go +++ b/challenge/http01/http_challenge_test.go @@ -67,7 +67,7 @@ func TestProviderServer_GetAddress(t *testing.T) { } func TestChallenge(t *testing.T) { - apiURL := tester.MockACMEServer().Build(t) + apiURL, client := tester.MockACMEServer().BuildHTTPS(t) providerServer := NewProviderServer("", "23457") @@ -100,7 +100,7 @@ func TestChallenge(t *testing.T) { privateKey, err := rsa.GenerateKey(rand.Reader, 1024) require.NoError(t, err, "Could not generate test key") - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", privateKey) + core, err := api.New(client, "lego-test", apiURL+"/dir", "", privateKey) require.NoError(t, err) solver := NewChallenge(core, validate, providerServer) @@ -123,7 +123,7 @@ func TestChallengeUnix(t *testing.T) { t.Skip("only for UNIX systems") } - apiURL := tester.MockACMEServer().Build(t) + apiURL, httpsClient := tester.MockACMEServer().BuildHTTPS(t) dir := t.TempDir() t.Cleanup(func() { _ = os.RemoveAll(dir) }) @@ -169,7 +169,7 @@ func TestChallengeUnix(t *testing.T) { privateKey, err := rsa.GenerateKey(rand.Reader, 1024) require.NoError(t, err, "Could not generate test key") - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", privateKey) + core, err := api.New(httpsClient, "lego-test", apiURL+"/dir", "", privateKey) require.NoError(t, err) solver := NewChallenge(core, validate, providerServer) @@ -188,12 +188,12 @@ func TestChallengeUnix(t *testing.T) { } func TestChallengeInvalidPort(t *testing.T) { - apiURL := tester.MockACMEServer().Build(t) + apiURL, client := tester.MockACMEServer().BuildHTTPS(t) privateKey, err := rsa.GenerateKey(rand.Reader, 1024) require.NoError(t, err, "Could not generate test key") - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", privateKey) + core, err := api.New(client, "lego-test", apiURL+"/dir", "", privateKey) require.NoError(t, err) validate := func(_ *api.Core, _ string, _ acme.Challenge) error { return nil } @@ -371,7 +371,7 @@ func TestChallengeWithProxy(t *testing.T) { func testServeWithProxy(t *testing.T, header, extra *testProxyHeader, expectError bool) { t.Helper() - apiURL := tester.MockACMEServer().Build(t) + apiURL, client := tester.MockACMEServer().BuildHTTPS(t) providerServer := NewProviderServer("localhost", "23457") if header != nil { @@ -414,7 +414,7 @@ func testServeWithProxy(t *testing.T, header, extra *testProxyHeader, expectErro privateKey, err := rsa.GenerateKey(rand.Reader, 1024) require.NoError(t, err, "Could not generate test key") - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", privateKey) + core, err := api.New(client, "lego-test", apiURL+"/dir", "", privateKey) require.NoError(t, err) solver := NewChallenge(core, validate, providerServer) diff --git a/challenge/resolver/solver_manager_test.go b/challenge/resolver/solver_manager_test.go index a0f4630ed..8337463fd 100644 --- a/challenge/resolver/solver_manager_test.go +++ b/challenge/resolver/solver_manager_test.go @@ -37,7 +37,7 @@ func TestValidate(t *testing.T) { privateKey, _ := rsa.GenerateKey(rand.Reader, 1024) - apiURL := tester.MockACMEServer(). + apiURL, client := tester.MockACMEServer(). Route("POST /chlg", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { if err := validateNoBody(privateKey, req); err != nil { @@ -46,7 +46,7 @@ func TestValidate(t *testing.T) { } rw.Header().Set("Link", - fmt.Sprintf(`; rel="up"`, req.Context().Value(http.LocalAddrContextKey))) + fmt.Sprintf(`; rel="up"`, req.Context().Value(http.LocalAddrContextKey))) st := statuses[0] statuses = statuses[1:] @@ -74,9 +74,9 @@ func TestValidate(t *testing.T) { servermock.JSONEncode(authorization).ServeHTTP(rw, req) })). - Build(t) + BuildHTTPS(t) - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", privateKey) + core, err := api.New(client, "lego-test", apiURL+"/dir", "", privateKey) require.NoError(t, err) testCases := []struct { diff --git a/challenge/tlsalpn01/tls_alpn_challenge_test.go b/challenge/tlsalpn01/tls_alpn_challenge_test.go index 5e0469d8c..72ccae603 100644 --- a/challenge/tlsalpn01/tls_alpn_challenge_test.go +++ b/challenge/tlsalpn01/tls_alpn_challenge_test.go @@ -8,7 +8,6 @@ import ( "crypto/tls" "encoding/asn1" "net" - "net/http" "testing" "github.com/go-acme/lego/v4/acme" @@ -21,7 +20,7 @@ import ( ) func TestChallenge(t *testing.T) { - apiURL := tester.MockACMEServer().Build(t) + apiURL, client := tester.MockACMEServer().BuildHTTPS(t) domain := "localhost" port := "24457" @@ -69,7 +68,7 @@ func TestChallenge(t *testing.T) { privateKey, err := rsa.GenerateKey(rand.Reader, 1024) require.NoError(t, err, "Could not generate test key") - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", privateKey) + core, err := api.New(client, "lego-test", apiURL+"/dir", "", privateKey) require.NoError(t, err) solver := NewChallenge( @@ -93,12 +92,12 @@ func TestChallenge(t *testing.T) { } func TestChallengeInvalidPort(t *testing.T) { - apiURL := tester.MockACMEServer().Build(t) + apiURL, client := tester.MockACMEServer().BuildHTTPS(t) privateKey, err := rsa.GenerateKey(rand.Reader, 1024) require.NoError(t, err, "Could not generate test key") - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", privateKey) + core, err := api.New(client, "lego-test", apiURL+"/dir", "", privateKey) require.NoError(t, err) solver := NewChallenge( @@ -123,7 +122,7 @@ func TestChallengeInvalidPort(t *testing.T) { } func TestChallengeIPaddress(t *testing.T) { - apiURL := tester.MockACMEServer().Build(t) + apiURL, client := tester.MockACMEServer().BuildHTTPS(t) domain := "127.0.0.1" port := "24457" @@ -170,7 +169,7 @@ func TestChallengeIPaddress(t *testing.T) { privateKey, err := rsa.GenerateKey(rand.Reader, 1024) require.NoError(t, err, "Could not generate test key") - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", privateKey) + core, err := api.New(client, "lego-test", apiURL+"/dir", "", privateKey) require.NoError(t, err) solver := NewChallenge( diff --git a/lego/client_test.go b/lego/client_test.go index 8a18c47c7..4b8a38f5f 100644 --- a/lego/client_test.go +++ b/lego/client_test.go @@ -13,7 +13,7 @@ import ( ) func TestNewClient(t *testing.T) { - apiURL := tester.MockACMEServer().Build(t) + apiURL, httpsClient := tester.MockACMEServer().BuildHTTPS(t) key, err := rsa.GenerateKey(rand.Reader, 1024) require.NoError(t, err, "Could not generate test key") @@ -26,6 +26,7 @@ func TestNewClient(t *testing.T) { config := NewConfig(user) config.CADirURL = apiURL + "/dir" + config.HTTPClient = httpsClient client, err := NewClient(config) require.NoError(t, err, "Could not create client") diff --git a/platform/tester/api.go b/platform/tester/api.go index 4ffb62a50..5a7c52038 100644 --- a/platform/tester/api.go +++ b/platform/tester/api.go @@ -17,7 +17,7 @@ func MockACMEServer() *servermock.Builder[string] { return server.URL, nil }). Route("GET /dir", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - serverURL := fmt.Sprintf("http://%s", req.Context().Value(http.LocalAddrContextKey)) + serverURL := fmt.Sprintf("https://%s", req.Context().Value(http.LocalAddrContextKey)) servermock.JSONEncode(acme.Directory{ NewNonceURL: serverURL + "/nonce", diff --git a/platform/tester/servermock/builder.go b/platform/tester/servermock/builder.go index e3b41e5c3..d62cec14d 100644 --- a/platform/tester/servermock/builder.go +++ b/platform/tester/servermock/builder.go @@ -70,3 +70,15 @@ func (b *Builder[T]) Build(t *testing.T) T { return client } + +func (b *Builder[T]) BuildHTTPS(t *testing.T) (T, *http.Client) { + t.Helper() + + server := httptest.NewTLSServer(b.mux) + t.Cleanup(server.Close) + + client, err := b.clientBuilder(server) + require.NoError(t, err) + + return client, server.Client() +} diff --git a/registration/registar_test.go b/registration/registar_test.go index 0b3f88f98..2074b8f0f 100644 --- a/registration/registar_test.go +++ b/registration/registar_test.go @@ -16,7 +16,7 @@ import ( ) func TestRegistrar_ResolveAccountByKey(t *testing.T) { - apiURL := tester.MockACMEServer(). + apiURL, client := tester.MockACMEServer(). Route("/account", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { rw.Header().Set("Location", @@ -24,7 +24,7 @@ func TestRegistrar_ResolveAccountByKey(t *testing.T) { servermock.JSONEncode(acme.Account{Status: "valid"}).ServeHTTP(rw, req) })). - Build(t) + BuildHTTPS(t) key, err := rsa.GenerateKey(rand.Reader, 1024) require.NoError(t, err, "Could not generate test key") @@ -35,7 +35,7 @@ func TestRegistrar_ResolveAccountByKey(t *testing.T) { privatekey: key, } - core, err := api.New(http.DefaultClient, "lego-test", apiURL+"/dir", "", key) + core, err := api.New(client, "lego-test", apiURL+"/dir", "", key) require.NoError(t, err) registrar := NewRegistrar(core, user)