2018-11-08 19:51:13 +02:00
|
|
|
package httpreq
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"net/url"
|
2019-02-04 23:54:54 +02:00
|
|
|
"path"
|
2018-11-08 19:51:13 +02:00
|
|
|
"testing"
|
|
|
|
|
2020-09-02 03:20:01 +02:00
|
|
|
"github.com/go-acme/lego/v4/platform/tester"
|
2018-11-08 19:51:13 +02:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
2020-03-12 00:51:10 +02:00
|
|
|
var envTest = tester.NewEnvTest(EnvEndpoint, EnvMode, EnvUsername, EnvPassword)
|
2018-11-08 19:51:13 +02:00
|
|
|
|
|
|
|
func TestNewDNSProvider(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
desc string
|
|
|
|
envVars map[string]string
|
|
|
|
expected string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
desc: "success",
|
|
|
|
envVars: map[string]string{
|
2020-03-12 00:51:10 +02:00
|
|
|
EnvEndpoint: "http://localhost:8090",
|
2018-11-08 19:51:13 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "invalid URL",
|
|
|
|
envVars: map[string]string{
|
2020-03-12 00:51:10 +02:00
|
|
|
EnvEndpoint: ":",
|
2018-11-08 19:51:13 +02:00
|
|
|
},
|
2020-02-26 01:02:29 +02:00
|
|
|
expected: `httpreq: parse ":": missing protocol scheme`,
|
2018-11-08 19:51:13 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "missing endpoint",
|
|
|
|
envVars: map[string]string{
|
2020-03-12 00:51:10 +02:00
|
|
|
EnvEndpoint: "",
|
2018-11-08 19:51:13 +02:00
|
|
|
},
|
|
|
|
expected: "httpreq: some credentials information are missing: HTTPREQ_ENDPOINT",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range testCases {
|
|
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
|
|
defer envTest.RestoreEnv()
|
|
|
|
envTest.ClearEnv()
|
|
|
|
|
|
|
|
envTest.Apply(test.envVars)
|
|
|
|
|
|
|
|
p, err := NewDNSProvider()
|
|
|
|
|
2021-03-04 21:16:59 +02:00
|
|
|
if test.expected == "" {
|
2018-11-08 19:51:13 +02:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, p)
|
|
|
|
require.NotNil(t, p.config)
|
|
|
|
} else {
|
|
|
|
require.EqualError(t, err, test.expected)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNewDNSProviderConfig(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
desc string
|
|
|
|
endpoint *url.URL
|
|
|
|
expected string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
desc: "success",
|
|
|
|
endpoint: mustParse("http://localhost:8090"),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "missing endpoint",
|
|
|
|
expected: "httpreq: the endpoint is missing",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range testCases {
|
|
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
|
|
config := NewDefaultConfig()
|
|
|
|
config.Endpoint = test.endpoint
|
|
|
|
|
|
|
|
p, err := NewDNSProviderConfig(config)
|
|
|
|
|
2021-03-04 21:16:59 +02:00
|
|
|
if test.expected == "" {
|
2018-11-08 19:51:13 +02:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, p)
|
|
|
|
require.NotNil(t, p.config)
|
|
|
|
} else {
|
|
|
|
require.EqualError(t, err, test.expected)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNewDNSProvider_Present(t *testing.T) {
|
|
|
|
envTest.RestoreEnv()
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
desc string
|
|
|
|
mode string
|
|
|
|
username string
|
|
|
|
password string
|
2019-02-04 23:54:54 +02:00
|
|
|
pathPrefix string
|
2018-11-08 19:51:13 +02:00
|
|
|
handler http.HandlerFunc
|
|
|
|
expectedError string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
desc: "success",
|
|
|
|
handler: successHandler,
|
|
|
|
},
|
2019-02-04 23:54:54 +02:00
|
|
|
{
|
|
|
|
desc: "success with path prefix",
|
|
|
|
handler: successHandler,
|
|
|
|
pathPrefix: "/api/acme/",
|
|
|
|
},
|
2018-11-08 19:51:13 +02:00
|
|
|
{
|
|
|
|
desc: "error",
|
|
|
|
handler: http.NotFound,
|
2023-05-05 09:49:38 +02:00
|
|
|
expectedError: "httpreq: unexpected status code: [status code: 404] body: 404 page not found",
|
2018-11-08 19:51:13 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "success raw mode",
|
|
|
|
mode: "RAW",
|
|
|
|
handler: successRawModeHandler,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "error raw mode",
|
|
|
|
mode: "RAW",
|
|
|
|
handler: http.NotFound,
|
2023-05-05 09:49:38 +02:00
|
|
|
expectedError: "httpreq: unexpected status code: [status code: 404] body: 404 page not found",
|
2018-11-08 19:51:13 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "basic auth",
|
|
|
|
username: "bar",
|
|
|
|
password: "foo",
|
|
|
|
handler: func(rw http.ResponseWriter, req *http.Request) {
|
|
|
|
username, password, ok := req.BasicAuth()
|
|
|
|
if username != "bar" || password != "foo" || !ok {
|
2021-11-03 21:39:12 +02:00
|
|
|
rw.Header().Set("WWW-Authenticate", fmt.Sprintf(`Basic realm=%q`, "Please enter your username and password."))
|
2018-11-09 02:32:09 +02:00
|
|
|
http.Error(rw, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
2018-11-08 19:51:13 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Fprint(rw, "lego")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range testCases {
|
|
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
mux := http.NewServeMux()
|
|
|
|
server := httptest.NewServer(mux)
|
2021-11-02 01:52:38 +02:00
|
|
|
t.Cleanup(server.Close)
|
2018-11-08 19:51:13 +02:00
|
|
|
|
2023-05-05 09:49:38 +02:00
|
|
|
mux.HandleFunc(path.Join("/", test.pathPrefix, "present"), test.handler)
|
|
|
|
|
2018-11-08 19:51:13 +02:00
|
|
|
config := NewDefaultConfig()
|
2019-02-04 23:54:54 +02:00
|
|
|
config.Endpoint = mustParse(server.URL + test.pathPrefix)
|
2018-11-08 19:51:13 +02:00
|
|
|
config.Mode = test.mode
|
|
|
|
config.Username = test.username
|
|
|
|
config.Password = test.password
|
|
|
|
|
|
|
|
p, err := NewDNSProviderConfig(config)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = p.Present("domain", "token", "key")
|
|
|
|
if test.expectedError == "" {
|
|
|
|
require.NoError(t, err)
|
|
|
|
} else {
|
|
|
|
require.EqualError(t, err, test.expectedError)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNewDNSProvider_Cleanup(t *testing.T) {
|
|
|
|
envTest.RestoreEnv()
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
desc string
|
|
|
|
mode string
|
|
|
|
username string
|
|
|
|
password string
|
|
|
|
handler http.HandlerFunc
|
|
|
|
expectedError string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
desc: "success",
|
|
|
|
handler: successHandler,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "error",
|
|
|
|
handler: http.NotFound,
|
2023-05-05 09:49:38 +02:00
|
|
|
expectedError: "httpreq: unexpected status code: [status code: 404] body: 404 page not found",
|
2018-11-08 19:51:13 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "success raw mode",
|
|
|
|
mode: "RAW",
|
|
|
|
handler: successRawModeHandler,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "error raw mode",
|
|
|
|
mode: "RAW",
|
|
|
|
handler: http.NotFound,
|
2023-05-05 09:49:38 +02:00
|
|
|
expectedError: "httpreq: unexpected status code: [status code: 404] body: 404 page not found",
|
2018-11-08 19:51:13 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "basic auth",
|
|
|
|
username: "bar",
|
|
|
|
password: "foo",
|
|
|
|
handler: func(rw http.ResponseWriter, req *http.Request) {
|
|
|
|
username, password, ok := req.BasicAuth()
|
|
|
|
if username != "bar" || password != "foo" || !ok {
|
2021-11-03 21:39:12 +02:00
|
|
|
rw.Header().Set("WWW-Authenticate", fmt.Sprintf(`Basic realm=%q`, "Please enter your username and password."))
|
2018-11-09 02:32:09 +02:00
|
|
|
http.Error(rw, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
2018-11-08 19:51:13 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
fmt.Fprint(rw, "lego")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range testCases {
|
|
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
mux := http.NewServeMux()
|
|
|
|
server := httptest.NewServer(mux)
|
2021-11-02 01:52:38 +02:00
|
|
|
t.Cleanup(server.Close)
|
2018-11-08 19:51:13 +02:00
|
|
|
|
2023-05-05 09:49:38 +02:00
|
|
|
mux.HandleFunc("/cleanup", test.handler)
|
|
|
|
|
2018-11-08 19:51:13 +02:00
|
|
|
config := NewDefaultConfig()
|
|
|
|
config.Endpoint = mustParse(server.URL)
|
|
|
|
config.Mode = test.mode
|
|
|
|
config.Username = test.username
|
|
|
|
config.Password = test.password
|
|
|
|
|
|
|
|
p, err := NewDNSProviderConfig(config)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = p.CleanUp("domain", "token", "key")
|
|
|
|
if test.expectedError == "" {
|
|
|
|
require.NoError(t, err)
|
|
|
|
} else {
|
|
|
|
require.EqualError(t, err, test.expectedError)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func successHandler(rw http.ResponseWriter, req *http.Request) {
|
|
|
|
if req.Method != http.MethodPost {
|
|
|
|
http.Error(rw, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
msg := &message{}
|
|
|
|
err := json.NewDecoder(req.Body).Decode(msg)
|
|
|
|
if err != nil {
|
|
|
|
http.Error(rw, err.Error(), http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Fprint(rw, "lego")
|
|
|
|
}
|
|
|
|
|
|
|
|
func successRawModeHandler(rw http.ResponseWriter, req *http.Request) {
|
|
|
|
if req.Method != http.MethodPost {
|
|
|
|
http.Error(rw, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
msg := &messageRaw{}
|
|
|
|
err := json.NewDecoder(req.Body).Decode(msg)
|
|
|
|
if err != nil {
|
|
|
|
http.Error(rw, err.Error(), http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Fprint(rw, "lego")
|
|
|
|
}
|
|
|
|
|
|
|
|
func mustParse(rawURL string) *url.URL {
|
|
|
|
uri, err := url.Parse(rawURL)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return uri
|
|
|
|
}
|