fix: enforce HTTPS to the ACME server (#2608)

This commit is contained in:
Ludovic Fernandez 2025-08-01 16:35:07 +02:00 committed by GitHub
commit 238454b5f7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 161 additions and 107 deletions

View file

@ -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)

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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://")
}

View file

@ -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 {

View file

@ -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(`<http://%s/certificate/1>;title="foo";rel="alternate"`, req.Context().Value(http.LocalAddrContextKey)))
fmt.Sprintf(`<https://%s/certificate/1>;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})

View file

@ -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})

View file

@ -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 {

View file

@ -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)

View file

@ -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(`<http://%s/my-authz>; rel="up"`, req.Context().Value(http.LocalAddrContextKey)))
fmt.Sprintf(`<https://%s/my-authz>; 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 {

View file

@ -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(

View file

@ -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")

View file

@ -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",

View file

@ -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()
}

View file

@ -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)