forked from TrueCloudLab/lego
Migrate to golangci-lint (#644)
* refactor: linting. - errcheck - govet - golint - goconst - spellcheck - ... * refactor: migrate from gometalinter to golangci-lint.
This commit is contained in:
parent
38ffd0577b
commit
ad20bf90ff
74 changed files with 950 additions and 810 deletions
42
.golangci.toml
Normal file
42
.golangci.toml
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
[run]
|
||||||
|
deadline = "2m"
|
||||||
|
|
||||||
|
[linters-settings]
|
||||||
|
|
||||||
|
[linters-settings.govet]
|
||||||
|
check-shadowing = true
|
||||||
|
|
||||||
|
[linters-settings.gocyclo]
|
||||||
|
min-complexity = 16.0
|
||||||
|
|
||||||
|
[linters-settings.maligned]
|
||||||
|
suggest-new = true
|
||||||
|
|
||||||
|
[linters-settings.goconst]
|
||||||
|
min-len = 2.0
|
||||||
|
min-occurrences = 3.0
|
||||||
|
|
||||||
|
[linters-settings.misspell]
|
||||||
|
locale = "US"
|
||||||
|
|
||||||
|
[linters]
|
||||||
|
enable-all = true
|
||||||
|
disable = [
|
||||||
|
"maligned",
|
||||||
|
"lll",
|
||||||
|
"gas",
|
||||||
|
"dupl",
|
||||||
|
"prealloc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[issues]
|
||||||
|
max-per-linter = 0
|
||||||
|
max-same = 0
|
||||||
|
exclude = [
|
||||||
|
"session.New is deprecated:", # providers/dns/route53/route53_integration_test.go | providers/dns/route53/route53_test.go
|
||||||
|
"func (.+)disableAuthz(.) is unused", # acme/client.go#disableAuthz
|
||||||
|
"type (.+)deactivateAuthMessage(.) is unused", # acme/messages.go#deactivateAuthMessage
|
||||||
|
"(.)limitReader(.) - (.)numBytes(.) always receives (.)1048576(.)", # acme/crypto.go#limitReader
|
||||||
|
"cyclomatic complexity (\\d+) of func (.)NewDNSChallengeProviderByName(.) is high", # providers/dns/dns_providers.go#NewDNSChallengeProviderByName
|
||||||
|
"cyclomatic complexity (\\d+) of func (.)setup(.) is high", # cli_handler.go#setup
|
||||||
|
]
|
|
@ -18,9 +18,8 @@ before_install:
|
||||||
- chmod +x $GOPATH/bin/dep
|
- chmod +x $GOPATH/bin/dep
|
||||||
|
|
||||||
# Install linters and misspell
|
# Install linters and misspell
|
||||||
- go get -u github.com/alecthomas/gometalinter
|
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.10.2
|
||||||
- gometalinter --install
|
- golangci-lint --version
|
||||||
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- dep status -v
|
- dep status -v
|
||||||
|
|
4
Makefile
4
Makefile
|
@ -17,8 +17,8 @@ dependencies:
|
||||||
test: clean
|
test: clean
|
||||||
go test -v -cover ./...
|
go test -v -cover ./...
|
||||||
|
|
||||||
checks: check-fmt
|
checks:
|
||||||
gometalinter ./...
|
golangci-lint run
|
||||||
|
|
||||||
check-fmt: SHELL := /bin/bash
|
check-fmt: SHELL := /bin/bash
|
||||||
check-fmt:
|
check-fmt:
|
||||||
|
|
|
@ -26,6 +26,9 @@ const (
|
||||||
// “new-reg”, “new-authz” and “new-cert” endpoints. From the documentation the
|
// “new-reg”, “new-authz” and “new-cert” endpoints. From the documentation the
|
||||||
// limitation is 20 requests per second, but using 20 as value doesn't work but 18 do
|
// limitation is 20 requests per second, but using 20 as value doesn't work but 18 do
|
||||||
overallRequestLimit = 18
|
overallRequestLimit = 18
|
||||||
|
|
||||||
|
statusValid = "valid"
|
||||||
|
statusInvalid = "invalid"
|
||||||
)
|
)
|
||||||
|
|
||||||
// User interface is to be implemented by users of this library.
|
// User interface is to be implemented by users of this library.
|
||||||
|
@ -43,7 +46,7 @@ type solver interface {
|
||||||
|
|
||||||
// Interface for challenges like dns, where we can set a record in advance for ALL challenges.
|
// Interface for challenges like dns, where we can set a record in advance for ALL challenges.
|
||||||
// This saves quite a bit of time vs creating the records and solving them serially.
|
// This saves quite a bit of time vs creating the records and solving them serially.
|
||||||
type presolver interface {
|
type preSolver interface {
|
||||||
PreSolve(challenge challenge, domain string) error
|
PreSolve(challenge challenge, domain string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,9 +505,9 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple b
|
||||||
// Start by checking to see if the certificate was based off a CSR, and
|
// Start by checking to see if the certificate was based off a CSR, and
|
||||||
// use that if it's defined.
|
// use that if it's defined.
|
||||||
if len(cert.CSR) > 0 {
|
if len(cert.CSR) > 0 {
|
||||||
csr, err := pemDecodeTox509CSR(cert.CSR)
|
csr, errP := pemDecodeTox509CSR(cert.CSR)
|
||||||
if err != nil {
|
if errP != nil {
|
||||||
return nil, err
|
return nil, errP
|
||||||
}
|
}
|
||||||
newCert, failures := c.ObtainCertificateForCSR(*csr, bundle)
|
newCert, failures := c.ObtainCertificateForCSR(*csr, bundle)
|
||||||
return newCert, failures
|
return newCert, failures
|
||||||
|
@ -537,7 +540,6 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) createOrderForIdentifiers(domains []string) (orderResource, error) {
|
func (c *Client) createOrderForIdentifiers(domains []string) (orderResource, error) {
|
||||||
|
|
||||||
var identifiers []identifier
|
var identifiers []identifier
|
||||||
for _, domain := range domains {
|
for _, domain := range domains {
|
||||||
identifiers = append(identifiers, identifier{Type: "dns", Value: domain})
|
identifiers = append(identifiers, identifier{Type: "dns", Value: domain})
|
||||||
|
@ -577,16 +579,16 @@ func (c *Client) solveChallengeForAuthz(authorizations []authorization) error {
|
||||||
|
|
||||||
// loop through the resources, basically through the domains. First pass just selects a solver for each authz.
|
// loop through the resources, basically through the domains. First pass just selects a solver for each authz.
|
||||||
for _, authz := range authorizations {
|
for _, authz := range authorizations {
|
||||||
if authz.Status == "valid" {
|
if authz.Status == statusValid {
|
||||||
// Boulder might recycle recent validated authz (see issue #267)
|
// Boulder might recycle recent validated authz (see issue #267)
|
||||||
log.Infof("[%s] acme: Authorization already valid; skipping challenge", authz.Identifier.Value)
|
log.Infof("[%s] acme: Authorization already valid; skipping challenge", authz.Identifier.Value)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if i, solver := c.chooseSolver(authz, authz.Identifier.Value); solver != nil {
|
if i, solvr := c.chooseSolver(authz, authz.Identifier.Value); solvr != nil {
|
||||||
authSolvers = append(authSolvers, &selectedAuthSolver{
|
authSolvers = append(authSolvers, &selectedAuthSolver{
|
||||||
authz: authz,
|
authz: authz,
|
||||||
challengeIndex: i,
|
challengeIndex: i,
|
||||||
solver: solver,
|
solver: solvr,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
failures[authz.Identifier.Value] = fmt.Errorf("[%s] acme: Could not determine solvers", authz.Identifier.Value)
|
failures[authz.Identifier.Value] = fmt.Errorf("[%s] acme: Could not determine solvers", authz.Identifier.Value)
|
||||||
|
@ -597,7 +599,7 @@ func (c *Client) solveChallengeForAuthz(authorizations []authorization) error {
|
||||||
for _, item := range authSolvers {
|
for _, item := range authSolvers {
|
||||||
authz := item.authz
|
authz := item.authz
|
||||||
i := item.challengeIndex
|
i := item.challengeIndex
|
||||||
if presolver, ok := item.solver.(presolver); ok {
|
if presolver, ok := item.solver.(preSolver); ok {
|
||||||
if err := presolver.PreSolve(authz.Challenges[i], authz.Identifier.Value); err != nil {
|
if err := presolver.PreSolve(authz.Challenges[i], authz.Identifier.Value); err != nil {
|
||||||
failures[authz.Identifier.Value] = err
|
failures[authz.Identifier.Value] = err
|
||||||
}
|
}
|
||||||
|
@ -607,12 +609,12 @@ func (c *Client) solveChallengeForAuthz(authorizations []authorization) error {
|
||||||
defer func() {
|
defer func() {
|
||||||
// clean all created TXT records
|
// clean all created TXT records
|
||||||
for _, item := range authSolvers {
|
for _, item := range authSolvers {
|
||||||
if cleanup, ok := item.solver.(cleanup); ok {
|
if clean, ok := item.solver.(cleanup); ok {
|
||||||
if failures[item.authz.Identifier.Value] != nil {
|
if failures[item.authz.Identifier.Value] != nil {
|
||||||
// already failed in previous loop
|
// already failed in previous loop
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
err := cleanup.CleanUp(item.authz.Challenges[item.challengeIndex], item.authz.Identifier.Value)
|
err := clean.CleanUp(item.authz.Challenges[item.challengeIndex], item.authz.Identifier.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("Error cleaning up %s: %v ", item.authz.Identifier.Value, err)
|
log.Warnf("Error cleaning up %s: %v ", item.authz.Identifier.Value, err)
|
||||||
}
|
}
|
||||||
|
@ -755,7 +757,7 @@ func (c *Client) requestCertificateForCsr(order orderResource, bundle bool, csr
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if retOrder.Status == "invalid" {
|
if retOrder.Status == statusInvalid {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -765,7 +767,7 @@ func (c *Client) requestCertificateForCsr(order orderResource, bundle bool, csr
|
||||||
PrivateKey: privateKeyPem,
|
PrivateKey: privateKeyPem,
|
||||||
}
|
}
|
||||||
|
|
||||||
if retOrder.Status == "valid" {
|
if retOrder.Status == statusValid {
|
||||||
// if the certificate is available right away, short cut!
|
// if the certificate is available right away, short cut!
|
||||||
ok, err := c.checkCertResponse(retOrder, &certRes, bundle)
|
ok, err := c.checkCertResponse(retOrder, &certRes, bundle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -809,9 +811,8 @@ func (c *Client) requestCertificateForCsr(order orderResource, bundle bool, csr
|
||||||
// should already have the Domain (common name) field populated. If bundle is
|
// should already have the Domain (common name) field populated. If bundle is
|
||||||
// true, the certificate will be bundled with the issuer's cert.
|
// true, the certificate will be bundled with the issuer's cert.
|
||||||
func (c *Client) checkCertResponse(order orderMessage, certRes *CertificateResource, bundle bool) (bool, error) {
|
func (c *Client) checkCertResponse(order orderMessage, certRes *CertificateResource, bundle bool) (bool, error) {
|
||||||
|
|
||||||
switch order.Status {
|
switch order.Status {
|
||||||
case "valid":
|
case statusValid:
|
||||||
resp, err := httpGet(order.Certificate)
|
resp, err := httpGet(order.Certificate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
@ -860,7 +861,7 @@ func (c *Client) checkCertResponse(order orderMessage, certRes *CertificateResou
|
||||||
|
|
||||||
case "processing":
|
case "processing":
|
||||||
return false, nil
|
return false, nil
|
||||||
case "invalid":
|
case statusInvalid:
|
||||||
return false, errors.New("order has invalid state: invalid")
|
return false, errors.New("order has invalid state: invalid")
|
||||||
default:
|
default:
|
||||||
return false, nil
|
return false, nil
|
||||||
|
@ -922,12 +923,12 @@ func validate(j *jws, domain, uri string, c challenge) error {
|
||||||
// Repeatedly check the server for an updated status on our request.
|
// Repeatedly check the server for an updated status on our request.
|
||||||
for {
|
for {
|
||||||
switch chlng.Status {
|
switch chlng.Status {
|
||||||
case "valid":
|
case statusValid:
|
||||||
log.Infof("[%s] The server validated our request", domain)
|
log.Infof("[%s] The server validated our request", domain)
|
||||||
return nil
|
return nil
|
||||||
case "pending":
|
case "pending":
|
||||||
case "processing":
|
case "processing":
|
||||||
case "invalid":
|
case statusInvalid:
|
||||||
return handleChallengeError(chlng)
|
return handleChallengeError(chlng)
|
||||||
default:
|
default:
|
||||||
return errors.New("the server returned an unexpected state")
|
return errors.New("the server returned an unexpected state")
|
||||||
|
|
|
@ -35,7 +35,12 @@ func TestNewClient(t *testing.T) {
|
||||||
RevokeCertURL: "http://test",
|
RevokeCertURL: "http://test",
|
||||||
KeyChangeURL: "http://test",
|
KeyChangeURL: "http://test",
|
||||||
})
|
})
|
||||||
w.Write(data)
|
|
||||||
|
_, err = w.Write(data)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
client, err := NewClient(ts.URL, user, keyType)
|
client, err := NewClient(ts.URL, user, keyType)
|
||||||
|
@ -66,7 +71,12 @@ func TestClientOptPort(t *testing.T) {
|
||||||
RevokeCertURL: "http://test",
|
RevokeCertURL: "http://test",
|
||||||
KeyChangeURL: "http://test",
|
KeyChangeURL: "http://test",
|
||||||
})
|
})
|
||||||
w.Write(data)
|
|
||||||
|
_, err = w.Write(data)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
optPort := "1234"
|
optPort := "1234"
|
||||||
|
@ -75,7 +85,8 @@ func TestClientOptPort(t *testing.T) {
|
||||||
client, err := NewClient(ts.URL, user, RSA2048)
|
client, err := NewClient(ts.URL, user, RSA2048)
|
||||||
require.NoError(t, err, "Could not create client")
|
require.NoError(t, err, "Could not create client")
|
||||||
|
|
||||||
client.SetHTTPAddress(net.JoinHostPort(optHost, optPort))
|
err = client.SetHTTPAddress(net.JoinHostPort(optHost, optPort))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.IsType(t, &httpChallenge{}, client.solvers[HTTP01])
|
require.IsType(t, &httpChallenge{}, client.solvers[HTTP01])
|
||||||
httpSolver := client.solvers[HTTP01].(*httpChallenge)
|
httpSolver := client.solvers[HTTP01].(*httpChallenge)
|
||||||
|
@ -88,7 +99,8 @@ func TestClientOptPort(t *testing.T) {
|
||||||
|
|
||||||
// test setting different host
|
// test setting different host
|
||||||
optHost = "127.0.0.1"
|
optHost = "127.0.0.1"
|
||||||
client.SetHTTPAddress(net.JoinHostPort(optHost, optPort))
|
err = client.SetHTTPAddress(net.JoinHostPort(optHost, optPort))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, optHost, httpSolver.provider.(*HTTPProviderServer).iface, "iface")
|
assert.Equal(t, optHost, httpSolver.provider.(*HTTPProviderServer).iface, "iface")
|
||||||
}
|
}
|
||||||
|
@ -109,11 +121,17 @@ func TestNotHoldingLockWhileMakingHTTPRequests(t *testing.T) {
|
||||||
ch := make(chan bool)
|
ch := make(chan bool)
|
||||||
resultCh := make(chan bool)
|
resultCh := make(chan bool)
|
||||||
go func() {
|
go func() {
|
||||||
j.Nonce()
|
_, errN := j.Nonce()
|
||||||
|
if errN != nil {
|
||||||
|
t.Log(errN)
|
||||||
|
}
|
||||||
ch <- true
|
ch <- true
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
j.Nonce()
|
_, errN := j.Nonce()
|
||||||
|
if errN != nil {
|
||||||
|
t.Log(errN)
|
||||||
|
}
|
||||||
ch <- true
|
ch <- true
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
|
|
|
@ -81,20 +81,20 @@ func GetOCSPForCert(bundle []byte) ([]byte, *ocsp.Response, error) {
|
||||||
return nil, nil, errors.New("no issuing certificate URL")
|
return nil, nil, errors.New("no issuing certificate URL")
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := httpGet(issuedCert.IssuingCertificateURL[0])
|
resp, errC := httpGet(issuedCert.IssuingCertificateURL[0])
|
||||||
if err != nil {
|
if errC != nil {
|
||||||
return nil, nil, err
|
return nil, nil, errC
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
issuerBytes, err := ioutil.ReadAll(limitReader(resp.Body, 1024*1024))
|
issuerBytes, errC := ioutil.ReadAll(limitReader(resp.Body, 1024*1024))
|
||||||
if err != nil {
|
if errC != nil {
|
||||||
return nil, nil, err
|
return nil, nil, errC
|
||||||
}
|
}
|
||||||
|
|
||||||
issuerCert, err := x509.ParseCertificate(issuerBytes)
|
issuerCert, errC := x509.ParseCertificate(issuerBytes)
|
||||||
if err != nil {
|
if errC != nil {
|
||||||
return nil, nil, err
|
return nil, nil, errC
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert it into the slice on position 0
|
// Insert it into the slice on position 0
|
||||||
|
@ -258,15 +258,6 @@ func pemDecode(data []byte) (*pem.Block, error) {
|
||||||
return pemBlock, nil
|
return pemBlock, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func pemDecodeTox509(pem []byte) (*x509.Certificate, error) {
|
|
||||||
pemBlock, err := pemDecode(pem)
|
|
||||||
if pemBlock == nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return x509.ParseCertificate(pemBlock.Bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func pemDecodeTox509CSR(pem []byte) (*x509.CertificateRequest, error) {
|
func pemDecodeTox509CSR(pem []byte) (*x509.CertificateRequest, error) {
|
||||||
pemBlock, err := pemDecode(pem)
|
pemBlock, err := pemDecode(pem)
|
||||||
if pemBlock == nil {
|
if pemBlock == nil {
|
||||||
|
|
|
@ -25,14 +25,19 @@ func TestDNSValidServerResponse(t *testing.T) {
|
||||||
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Add("Replay-Nonce", "12345")
|
w.Header().Add("Replay-Nonce", "12345")
|
||||||
w.Write([]byte("{\"type\":\"dns01\",\"status\":\"valid\",\"uri\":\"http://some.url\",\"token\":\"http8\"}"))
|
|
||||||
|
_, err = w.Write([]byte("{\"type\":\"dns01\",\"status\":\"valid\",\"uri\":\"http://some.url\",\"token\":\"http8\"}"))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(time.Second * 2)
|
time.Sleep(time.Second * 2)
|
||||||
f := bufio.NewWriter(os.Stdout)
|
f := bufio.NewWriter(os.Stdout)
|
||||||
defer f.Flush()
|
defer f.Flush()
|
||||||
f.WriteString("\n")
|
_, _ = f.WriteString("\n")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
manualProvider, err := NewDNSProviderManual()
|
manualProvider, err := NewDNSProviderManual()
|
||||||
|
|
16
acme/http.go
16
acme/http.go
|
@ -148,29 +148,25 @@ func getJSON(uri string, respBody interface{}) (http.Header, error) {
|
||||||
func postJSON(j *jws, uri string, reqBody, respBody interface{}) (http.Header, error) {
|
func postJSON(j *jws, uri string, reqBody, respBody interface{}) (http.Header, error) {
|
||||||
jsonBytes, err := json.Marshal(reqBody)
|
jsonBytes, err := json.Marshal(reqBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("Failed to marshal network message")
|
return nil, errors.New("failed to marshal network message")
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := j.post(uri, jsonBytes)
|
resp, err := j.post(uri, jsonBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Failed to post JWS message. -> %v", err)
|
return nil, fmt.Errorf("failed to post JWS message. -> %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode >= http.StatusBadRequest {
|
if resp.StatusCode >= http.StatusBadRequest {
|
||||||
|
err = handleHTTPError(resp)
|
||||||
err := handleHTTPError(resp)
|
|
||||||
|
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
|
|
||||||
case NonceError:
|
case NonceError:
|
||||||
|
|
||||||
// Retry once if the nonce was invalidated
|
// Retry once if the nonce was invalidated
|
||||||
|
|
||||||
retryResp, err := j.post(uri, jsonBytes)
|
retryResp, errP := j.post(uri, jsonBytes)
|
||||||
if err != nil {
|
if errP != nil {
|
||||||
return nil, fmt.Errorf("Failed to post JWS message. -> %v", err)
|
return nil, fmt.Errorf("failed to post JWS message. -> %v", errP)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer retryResp.Body.Close()
|
defer retryResp.Body.Close()
|
||||||
|
|
|
@ -35,7 +35,7 @@ func (s *HTTPProviderServer) Present(domain, token, keyAuth string) error {
|
||||||
var err error
|
var err error
|
||||||
s.listener, err = net.Listen("tcp", net.JoinHostPort(s.iface, s.port))
|
s.listener, err = net.Listen("tcp", net.JoinHostPort(s.iface, s.port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Could not start HTTP server for challenge -> %v", err)
|
return fmt.Errorf("could not start HTTP server for challenge -> %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.done = make(chan bool)
|
s.done = make(chan bool)
|
||||||
|
@ -62,20 +62,31 @@ func (s *HTTPProviderServer) serve(domain, token, keyAuth string) {
|
||||||
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
|
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
|
||||||
if strings.HasPrefix(r.Host, domain) && r.Method == http.MethodGet {
|
if strings.HasPrefix(r.Host, domain) && r.Method == http.MethodGet {
|
||||||
w.Header().Add("Content-Type", "text/plain")
|
w.Header().Add("Content-Type", "text/plain")
|
||||||
w.Write([]byte(keyAuth))
|
_, err := w.Write([]byte(keyAuth))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
log.Infof("[%s] Served key authentication", domain)
|
log.Infof("[%s] Served key authentication", domain)
|
||||||
} else {
|
} else {
|
||||||
log.Warnf("Received request for domain %s with method %s but the domain did not match any challenge. Please ensure your are passing the HOST header properly.", r.Host, r.Method)
|
log.Warnf("Received request for domain %s with method %s but the domain did not match any challenge. Please ensure your are passing the HOST header properly.", r.Host, r.Method)
|
||||||
w.Write([]byte("TEST"))
|
_, err := w.Write([]byte("TEST"))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
httpServer := &http.Server{
|
httpServer := &http.Server{Handler: mux}
|
||||||
Handler: mux,
|
|
||||||
}
|
|
||||||
// Once httpServer is shut down we don't want any lingering
|
// Once httpServer is shut down we don't want any lingering
|
||||||
// connections, so disable KeepAlives.
|
// connections, so disable KeepAlives.
|
||||||
httpServer.SetKeepAlivesEnabled(false)
|
httpServer.SetKeepAlivesEnabled(false)
|
||||||
httpServer.Serve(s.listener)
|
|
||||||
|
err := httpServer.Serve(s.listener)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
s.done <- true
|
s.done <- true
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package acme
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
@ -65,7 +66,10 @@ func (t *TLSALPNProviderServer) Present(domain, token, keyAuth string) error {
|
||||||
|
|
||||||
// Shut the server down when we're finished.
|
// Shut the server down when we're finished.
|
||||||
go func() {
|
go func() {
|
||||||
http.Serve(t.listener, nil)
|
err := http.Serve(t.listener, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -3,16 +3,20 @@ package acme
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/xenolf/lego/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WaitFor polls the given function 'f', once every 'interval', up to 'timeout'.
|
// WaitFor polls the given function 'f', once every 'interval', up to 'timeout'.
|
||||||
func WaitFor(timeout, interval time.Duration, f func() (bool, error)) error {
|
func WaitFor(timeout, interval time.Duration, f func() (bool, error)) error {
|
||||||
|
log.Infof("Wait [timeout: %s, interval: %s]", timeout, interval)
|
||||||
|
|
||||||
var lastErr string
|
var lastErr string
|
||||||
timeup := time.After(timeout)
|
timeup := time.After(timeout)
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-timeup:
|
case <-timeup:
|
||||||
return fmt.Errorf("Time limit exceeded. Last error: %s", lastErr)
|
return fmt.Errorf("time limit exceeded: last error: %s", lastErr)
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
cli.go
2
cli.go
|
@ -177,7 +177,7 @@ func main() {
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "pem",
|
Name: "pem",
|
||||||
Usage: "Generate a .pem file by concatanating the .key and .crt files together.",
|
Usage: "Generate a .pem file by concatenating the .key and .crt files together.",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ func checkFolder(path string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) {
|
func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) {
|
||||||
|
|
||||||
if c.GlobalIsSet("http-timeout") {
|
if c.GlobalIsSet("http-timeout") {
|
||||||
acme.HTTPClient = http.Client{Timeout: time.Duration(c.GlobalInt("http-timeout")) * time.Second}
|
acme.HTTPClient = http.Client{Timeout: time.Duration(c.GlobalInt("http-timeout")) * time.Second}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +59,7 @@ func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) {
|
||||||
log.Fatal("You have to pass an account (email address) to the program using --email or -m")
|
log.Fatal("You have to pass an account (email address) to the program using --email or -m")
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: move to account struct? Currently MUST pass email.
|
// TODO: move to account struct? Currently MUST pass email.
|
||||||
acc := NewAccount(c.GlobalString("email"), conf)
|
acc := NewAccount(c.GlobalString("email"), conf)
|
||||||
|
|
||||||
keyType, err := conf.KeyType()
|
keyType, err := conf.KeyType()
|
||||||
|
@ -80,35 +79,37 @@ func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.GlobalIsSet("webroot") {
|
if c.GlobalIsSet("webroot") {
|
||||||
provider, err := webroot.NewHTTPProvider(c.GlobalString("webroot"))
|
provider, errO := webroot.NewHTTPProvider(c.GlobalString("webroot"))
|
||||||
if err != nil {
|
if errO != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(errO)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = client.SetChallengeProvider(acme.HTTP01, provider)
|
errO = client.SetChallengeProvider(acme.HTTP01, provider)
|
||||||
if err != nil {
|
if errO != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(errO)
|
||||||
}
|
}
|
||||||
|
|
||||||
// --webroot=foo indicates that the user specifically want to do a HTTP challenge
|
// --webroot=foo indicates that the user specifically want to do a HTTP challenge
|
||||||
// infer that the user also wants to exclude all other challenges
|
// infer that the user also wants to exclude all other challenges
|
||||||
client.ExcludeChallenges([]acme.Challenge{acme.DNS01, acme.TLSALPN01})
|
client.ExcludeChallenges([]acme.Challenge{acme.DNS01, acme.TLSALPN01})
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.GlobalIsSet("memcached-host") {
|
if c.GlobalIsSet("memcached-host") {
|
||||||
provider, err := memcached.NewMemcachedProvider(c.GlobalStringSlice("memcached-host"))
|
provider, errO := memcached.NewMemcachedProvider(c.GlobalStringSlice("memcached-host"))
|
||||||
if err != nil {
|
if errO != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(errO)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = client.SetChallengeProvider(acme.HTTP01, provider)
|
errO = client.SetChallengeProvider(acme.HTTP01, provider)
|
||||||
if err != nil {
|
if errO != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(errO)
|
||||||
}
|
}
|
||||||
|
|
||||||
// --memcached-host=foo:11211 indicates that the user specifically want to do a HTTP challenge
|
// --memcached-host=foo:11211 indicates that the user specifically want to do a HTTP challenge
|
||||||
// infer that the user also wants to exclude all other challenges
|
// infer that the user also wants to exclude all other challenges
|
||||||
client.ExcludeChallenges([]acme.Challenge{acme.DNS01, acme.TLSALPN01})
|
client.ExcludeChallenges([]acme.Challenge{acme.DNS01, acme.TLSALPN01})
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.GlobalIsSet("http") {
|
if c.GlobalIsSet("http") {
|
||||||
if !strings.Contains(c.GlobalString("http"), ":") {
|
if !strings.Contains(c.GlobalString("http"), ":") {
|
||||||
log.Fatalf("The --http switch only accepts interface:port or :port for its argument.")
|
log.Fatalf("The --http switch only accepts interface:port or :port for its argument.")
|
||||||
|
@ -124,18 +125,22 @@ func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) {
|
||||||
if !strings.Contains(c.GlobalString("tls"), ":") {
|
if !strings.Contains(c.GlobalString("tls"), ":") {
|
||||||
log.Fatalf("The --tls switch only accepts interface:port or :port for its argument.")
|
log.Fatalf("The --tls switch only accepts interface:port or :port for its argument.")
|
||||||
}
|
}
|
||||||
client.SetTLSAddress(c.GlobalString("tls"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.GlobalIsSet("dns") {
|
err = client.SetTLSAddress(c.GlobalString("tls"))
|
||||||
provider, err := dns.NewDNSChallengeProviderByName(c.GlobalString("dns"))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = client.SetChallengeProvider(acme.DNS01, provider)
|
if c.GlobalIsSet("dns") {
|
||||||
if err != nil {
|
provider, errO := dns.NewDNSChallengeProviderByName(c.GlobalString("dns"))
|
||||||
log.Fatal(err)
|
if errO != nil {
|
||||||
|
log.Fatal(errO)
|
||||||
|
}
|
||||||
|
|
||||||
|
errO = client.SetChallengeProvider(acme.DNS01, provider)
|
||||||
|
if errO != nil {
|
||||||
|
log.Fatal(errO)
|
||||||
}
|
}
|
||||||
|
|
||||||
// --dns=foo indicates that the user specifically want to do a DNS challenge
|
// --dns=foo indicates that the user specifically want to do a DNS challenge
|
||||||
|
@ -311,7 +316,10 @@ func run(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
acc.Registration = reg
|
acc.Registration = reg
|
||||||
acc.Save()
|
err = acc.Save()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
log.Print("!!!! HEADS UP !!!!")
|
log.Print("!!!! HEADS UP !!!!")
|
||||||
log.Printf(`
|
log.Printf(`
|
||||||
|
@ -421,8 +429,8 @@ func renew(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.IsSet("days") {
|
if c.IsSet("days") {
|
||||||
expTime, err := acme.GetPEMCertExpiration(certBytes)
|
expTime, errE := acme.GetPEMCertExpiration(certBytes)
|
||||||
if err != nil {
|
if errE != nil {
|
||||||
log.Printf("Could not get Certification expiration for domain %s", domain)
|
log.Printf("Could not get Certification expiration for domain %s", domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,14 +445,14 @@ func renew(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var certRes acme.CertificateResource
|
var certRes acme.CertificateResource
|
||||||
if err := json.Unmarshal(metaBytes, &certRes); err != nil {
|
if err = json.Unmarshal(metaBytes, &certRes); err != nil {
|
||||||
log.Fatalf("Error while marshalling the meta data for domain %s\n\t%v", domain, err)
|
log.Fatalf("Error while marshaling the meta data for domain %s\n\t%v", domain, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Bool("reuse-key") {
|
if c.Bool("reuse-key") {
|
||||||
keyBytes, err := ioutil.ReadFile(privPath)
|
keyBytes, errR := ioutil.ReadFile(privPath)
|
||||||
if err != nil {
|
if errR != nil {
|
||||||
log.Fatalf("Error while loading the private key for domain %s\n\t%v", domain, err)
|
log.Fatalf("Error while loading the private key for domain %s\n\t%v", domain, errR)
|
||||||
}
|
}
|
||||||
certRes.PrivateKey = keyBytes
|
certRes.PrivateKey = keyBytes
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func generatePrivateKey(file string) (crypto.PrivateKey, error) {
|
func generatePrivateKey(file string) (crypto.PrivateKey, error) {
|
||||||
|
|
||||||
privateKey, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
|
privateKey, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -30,9 +29,12 @@ func generatePrivateKey(file string) (crypto.PrivateKey, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
defer certOut.Close()
|
||||||
|
|
||||||
pem.Encode(certOut, &pemKey)
|
err = pem.Encode(certOut, &pemKey)
|
||||||
certOut.Close()
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return privateKey, nil
|
return privateKey, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,7 +101,7 @@ func (e ErrCNAMERequired) Error() string {
|
||||||
e.Domain, e.Domain, e.FQDN, e.Target)
|
e.Domain, e.Domain, e.FQDN, e.Target)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the DNS-01 challenge. If there is an
|
// Present creates a TXT record to fulfill the DNS-01 challenge. If there is an
|
||||||
// existing account for the domain in the provider's storage then it will be
|
// existing account for the domain in the provider's storage then it will be
|
||||||
// used to set the challenge response TXT record with the ACME-DNS server and
|
// used to set the challenge response TXT record with the ACME-DNS server and
|
||||||
// issuance will continue. If there is not an account for the given domain
|
// issuance will continue. If there is not an account for the given domain
|
||||||
|
|
|
@ -105,7 +105,7 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
// Present creates a TXT record to fulfill the dns-01 challenge.
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
// "time"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge
|
// Present creates a TXT record to fulfill the dns-01 challenge
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
|
|
|
@ -353,7 +353,7 @@ func (d *DNSProvider) lookupViewID(viewName string) (uint, error) {
|
||||||
|
|
||||||
queryArgs := map[string]string{
|
queryArgs := map[string]string{
|
||||||
"parentId": strconv.FormatUint(uint64(confID), 10),
|
"parentId": strconv.FormatUint(uint64(confID), 10),
|
||||||
"name": d.config.DNSView,
|
"name": viewName,
|
||||||
"type": viewType,
|
"type": viewType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,11 @@ func handlerMock(method string, response *APIResponse, data interface{}) http.Ha
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rw.Write(content)
|
_, err = rw.Write(content)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge
|
// Present creates a TXT record to fulfill the dns-01 challenge
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,11 @@ func handlerMock(method string, response *apiResponse, data interface{}) http.Ha
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rw.Write(content)
|
_, err = rw.Write(content)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
return &DNSProvider{client: client}, nil
|
return &DNSProvider{client: client}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
// Present creates a TXT record to fulfill the dns-01 challenge.
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
return &DNSProvider{client: client}, nil
|
return &DNSProvider{client: client}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
// Present creates a TXT record to fulfill the dns-01 challenge.
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ func (d *DNSProvider) findTxtRecords(domain, fqdn string) ([]dnsimple.ZoneRecord
|
||||||
|
|
||||||
result, err := d.client.Zones.ListRecords(accountID, zoneName, &dnsimple.ZoneRecordListOptions{Name: recordName, Type: "TXT", ListOptions: dnsimple.ListOptions{}})
|
result, err := d.client.Zones.ListRecords(accountID, zoneName, &dnsimple.ZoneRecordListOptions{Name: recordName, Type: "TXT", ListOptions: dnsimple.ListOptions{}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []dnsimple.ZoneRecord{}, fmt.Errorf("API call has failed: %v", err)
|
return nil, fmt.Errorf("API call has failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.Data, nil
|
return result.Data, nil
|
||||||
|
|
|
@ -84,7 +84,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
return &DNSProvider{client: client}, nil
|
return &DNSProvider{client: client}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
// Present creates a TXT record to fulfill the dns-01 challenge.
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
zoneID, zoneName, err := d.getHostedZone(domain)
|
zoneID, zoneName, err := d.getHostedZone(domain)
|
||||||
|
|
|
@ -75,7 +75,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
return &DNSProvider{config: config}, nil
|
return &DNSProvider{config: config}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
// Present creates a TXT record to fulfill the dns-01 challenge.
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
_, txtRecord, _ := acme.DNS01Record(domain, keyAuth)
|
_, txtRecord, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
return updateTxtRecord(domain, d.config.Token, txtRecord, false)
|
return updateTxtRecord(domain, d.config.Token, txtRecord, false)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -32,7 +33,7 @@ func TestLiveDynPresent(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.Present(dynDomain, "", "123d==")
|
err = provider.Present(dynDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
|
@ -59,7 +59,7 @@ func NewDNSProviderProgram(program string) (*DNSProvider, error) {
|
||||||
return NewDNSProviderConfig(&Config{Program: program})
|
return NewDNSProviderConfig(&Config{Program: program})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
// Present creates a TXT record to fulfill the dns-01 challenge.
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
var args []string
|
var args []string
|
||||||
if d.config.Mode == "RAW" {
|
if d.config.Mode == "RAW" {
|
||||||
|
|
|
@ -93,7 +93,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
return &DNSProvider{client: client, config: config}, nil
|
return &DNSProvider{client: client, config: config}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
// Present creates a TXT record to fulfill the dns-01 challenge.
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
zone, recordName, err := d.FindZoneAndRecordName(fqdn, domain)
|
zone, recordName, err := d.FindZoneAndRecordName(fqdn, domain)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -39,7 +40,7 @@ func TestNewDNSProviderValid(t *testing.T) {
|
||||||
config.APISecret = "123"
|
config.APISecret = "123"
|
||||||
|
|
||||||
_, err := NewDNSProviderConfig(config)
|
_, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
|
@ -48,7 +49,7 @@ func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
os.Setenv("EXOSCALE_API_SECRET", "123")
|
os.Setenv("EXOSCALE_API_SECRET", "123")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||||
|
@ -60,32 +61,56 @@ func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||||
assert.EqualError(t, err, "exoscale: some credentials information are missing: EXOSCALE_API_KEY,EXOSCALE_API_SECRET")
|
assert.EqualError(t, err, "exoscale: some credentials information are missing: EXOSCALE_API_KEY,EXOSCALE_API_SECRET")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractRootRecordName(t *testing.T) {
|
func TestDNSProvider_FindZoneAndRecordName(t *testing.T) {
|
||||||
config := NewDefaultConfig()
|
config := NewDefaultConfig()
|
||||||
config.APIKey = "example@example.com"
|
config.APIKey = "example@example.com"
|
||||||
config.APISecret = "123"
|
config.APISecret = "123"
|
||||||
|
|
||||||
provider, err := NewDNSProviderConfig(config)
|
provider, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
zone, recordName, err := provider.FindZoneAndRecordName("_acme-challenge.bar.com.", "bar.com")
|
type expected struct {
|
||||||
assert.NoError(t, err)
|
zone string
|
||||||
assert.Equal(t, "bar.com", zone)
|
recordName string
|
||||||
assert.Equal(t, "_acme-challenge", recordName)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func TestExtractSubRecordName(t *testing.T) {
|
testCases := []struct {
|
||||||
config := NewDefaultConfig()
|
desc string
|
||||||
config.APIKey = "example@example.com"
|
fqdn string
|
||||||
config.APISecret = "123"
|
domain string
|
||||||
|
expected expected
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "Extract root record name",
|
||||||
|
fqdn: "_acme-challenge.bar.com.",
|
||||||
|
domain: "bar.com",
|
||||||
|
expected: expected{
|
||||||
|
zone: "bar.com",
|
||||||
|
recordName: "_acme-challenge",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Extract sub record name",
|
||||||
|
fqdn: "_acme-challenge.foo.bar.com.",
|
||||||
|
domain: "foo.bar.com",
|
||||||
|
expected: expected{
|
||||||
|
zone: "bar.com",
|
||||||
|
recordName: "_acme-challenge.foo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
provider, err := NewDNSProviderConfig(config)
|
for _, test := range testCases {
|
||||||
assert.NoError(t, err)
|
test := test
|
||||||
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
zone, recordName, err := provider.FindZoneAndRecordName("_acme-challenge.foo.bar.com.", "foo.bar.com")
|
zone, recordName, err := provider.FindZoneAndRecordName(test.fqdn, test.domain)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "bar.com", zone)
|
assert.Equal(t, test.expected.zone, zone)
|
||||||
assert.Equal(t, "_acme-challenge.foo", recordName)
|
assert.Equal(t, test.expected.recordName, recordName)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLiveExoscalePresent(t *testing.T) {
|
func TestLiveExoscalePresent(t *testing.T) {
|
||||||
|
@ -98,14 +123,14 @@ func TestLiveExoscalePresent(t *testing.T) {
|
||||||
config.APISecret = exoscaleAPISecret
|
config.APISecret = exoscaleAPISecret
|
||||||
|
|
||||||
provider, err := NewDNSProviderConfig(config)
|
provider, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.Present(exoscaleDomain, "", "123d==")
|
err = provider.Present(exoscaleDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Present Twice to handle create / update
|
// Present Twice to handle create / update
|
||||||
err = provider.Present(exoscaleDomain, "", "123d==")
|
err = provider.Present(exoscaleDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLiveExoscaleCleanUp(t *testing.T) {
|
func TestLiveExoscaleCleanUp(t *testing.T) {
|
||||||
|
@ -120,8 +145,8 @@ func TestLiveExoscaleCleanUp(t *testing.T) {
|
||||||
config.APISecret = exoscaleAPISecret
|
config.APISecret = exoscaleAPISecret
|
||||||
|
|
||||||
provider, err := NewDNSProviderConfig(config)
|
provider, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.CleanUp(exoscaleDomain, "", "123d==")
|
err = provider.CleanUp(exoscaleDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,10 +99,10 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
record := configdns.NewTxtRecord()
|
record := configdns.NewTxtRecord()
|
||||||
record.SetField("name", recordName)
|
_ = record.SetField("name", recordName)
|
||||||
record.SetField("ttl", d.config.TTL)
|
_ = record.SetField("ttl", d.config.TTL)
|
||||||
record.SetField("target", value)
|
_ = record.SetField("target", value)
|
||||||
record.SetField("active", true)
|
_ = record.SetField("active", true)
|
||||||
|
|
||||||
existingRecord := d.findExistingRecord(zone, recordName)
|
existingRecord := d.findExistingRecord(zone, recordName)
|
||||||
|
|
||||||
|
@ -110,8 +110,10 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
if reflect.DeepEqual(existingRecord.ToMap(), record.ToMap()) {
|
if reflect.DeepEqual(existingRecord.ToMap(), record.ToMap()) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
zone.RemoveRecord(existingRecord)
|
err = zone.RemoveRecord(existingRecord)
|
||||||
return d.createRecord(zone, record)
|
if err != nil {
|
||||||
|
return fmt.Errorf("fastdns: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return d.createRecord(zone, record)
|
return d.createRecord(zone, record)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -50,7 +51,7 @@ func TestNewDNSProviderValid(t *testing.T) {
|
||||||
config.AccessToken = "someaccesstoken"
|
config.AccessToken = "someaccesstoken"
|
||||||
|
|
||||||
_, err := NewDNSProviderConfig(config)
|
_, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
|
@ -61,7 +62,7 @@ func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
os.Setenv("AKAMAI_ACCESS_TOKEN", "someaccesstoken")
|
os.Setenv("AKAMAI_ACCESS_TOKEN", "someaccesstoken")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||||
|
@ -87,17 +88,17 @@ func TestLiveFastdnsPresent(t *testing.T) {
|
||||||
config.AccessToken = accessToken
|
config.AccessToken = accessToken
|
||||||
|
|
||||||
provider, err := NewDNSProviderConfig(config)
|
provider, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.Present(testDomain, "", "123d==")
|
err = provider.Present(testDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Present Twice to handle create / update
|
// Present Twice to handle create / update
|
||||||
err = provider.Present(testDomain, "", "123d==")
|
err = provider.Present(testDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractRootRecordName(t *testing.T) {
|
func TestDNSProvider_findZoneAndRecordName(t *testing.T) {
|
||||||
config := NewDefaultConfig()
|
config := NewDefaultConfig()
|
||||||
config.Host = "somehost"
|
config.Host = "somehost"
|
||||||
config.ClientToken = "someclienttoken"
|
config.ClientToken = "someclienttoken"
|
||||||
|
@ -105,28 +106,50 @@ func TestExtractRootRecordName(t *testing.T) {
|
||||||
config.AccessToken = "someaccesstoken"
|
config.AccessToken = "someaccesstoken"
|
||||||
|
|
||||||
provider, err := NewDNSProviderConfig(config)
|
provider, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
zone, recordName, err := provider.findZoneAndRecordName("_acme-challenge.bar.com.", "bar.com")
|
type expected struct {
|
||||||
assert.NoError(t, err)
|
zone string
|
||||||
assert.Equal(t, "bar.com", zone)
|
recordName string
|
||||||
assert.Equal(t, "_acme-challenge", recordName)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func TestExtractSubRecordName(t *testing.T) {
|
testCases := []struct {
|
||||||
config := NewDefaultConfig()
|
desc string
|
||||||
config.Host = "somehost"
|
fqdn string
|
||||||
config.ClientToken = "someclienttoken"
|
domain string
|
||||||
config.ClientSecret = "someclientsecret"
|
expected expected
|
||||||
config.AccessToken = "someaccesstoken"
|
}{
|
||||||
|
{
|
||||||
|
desc: "Extract root record name",
|
||||||
|
fqdn: "_acme-challenge.bar.com.",
|
||||||
|
domain: "bar.com",
|
||||||
|
expected: expected{
|
||||||
|
zone: "bar.com",
|
||||||
|
recordName: "_acme-challenge",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Extract sub record name",
|
||||||
|
fqdn: "_acme-challenge.foo.bar.com.",
|
||||||
|
domain: "foo.bar.com",
|
||||||
|
expected: expected{
|
||||||
|
zone: "bar.com",
|
||||||
|
recordName: "_acme-challenge.foo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
provider, err := NewDNSProviderConfig(config)
|
for _, test := range testCases {
|
||||||
assert.NoError(t, err)
|
test := test
|
||||||
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
zone, recordName, err := provider.findZoneAndRecordName("_acme-challenge.foo.bar.com.", "foo.bar.com")
|
zone, recordName, err := provider.findZoneAndRecordName(test.fqdn, test.domain)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "bar.com", zone)
|
assert.Equal(t, test.expected.zone, zone)
|
||||||
assert.Equal(t, "_acme-challenge.foo", recordName)
|
assert.Equal(t, test.expected.recordName, recordName)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLiveFastdnsCleanUp(t *testing.T) {
|
func TestLiveFastdnsCleanUp(t *testing.T) {
|
||||||
|
@ -143,8 +166,8 @@ func TestLiveFastdnsCleanUp(t *testing.T) {
|
||||||
config.AccessToken = accessToken
|
config.AccessToken = accessToken
|
||||||
|
|
||||||
provider, err := NewDNSProviderConfig(config)
|
provider, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.CleanUp(testDomain, "", "123d==")
|
err = provider.CleanUp(testDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,8 +82,6 @@ type responseBool struct {
|
||||||
Value bool `xml:"params>param>value>boolean"`
|
Value bool `xml:"params>param>value>boolean"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// POSTing/Marshalling/Unmarshalling
|
|
||||||
|
|
||||||
type rpcError struct {
|
type rpcError struct {
|
||||||
faultCode int
|
faultCode int
|
||||||
faultString string
|
faultString string
|
||||||
|
|
|
@ -230,9 +230,9 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// rpcCall makes an XML-RPC call to Gandi's RPC endpoint by
|
// rpcCall makes an XML-RPC call to Gandi's RPC endpoint by
|
||||||
// marshalling the data given in the call argument to XML and sending
|
// marshaling the data given in the call argument to XML and sending
|
||||||
// that via HTTP Post to Gandi. The response is then unmarshalled into
|
// that via HTTP Post to Gandi.
|
||||||
// the resp argument.
|
// The response is then unmarshalled into the resp argument.
|
||||||
func (d *DNSProvider) rpcCall(call *methodCall, resp response) error {
|
func (d *DNSProvider) rpcCall(call *methodCall, resp response) error {
|
||||||
// marshal
|
// marshal
|
||||||
b, err := xml.MarshalIndent(call, "", " ")
|
b, err := xml.MarshalIndent(call, "", " ")
|
||||||
|
|
|
@ -24,15 +24,15 @@ func TestDNSProvider(t *testing.T) {
|
||||||
fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
require.Equal(t, "text/xml", r.Header.Get("Content-Type"), "invalid content type")
|
require.Equal(t, "text/xml", r.Header.Get("Content-Type"), "invalid content type")
|
||||||
|
|
||||||
req, err := ioutil.ReadAll(r.Body)
|
req, errS := ioutil.ReadAll(r.Body)
|
||||||
require.NoError(t, err)
|
require.NoError(t, errS)
|
||||||
|
|
||||||
req = regexpDate.ReplaceAllLiteral(req, []byte(`[ACME Challenge 01 Jan 16 00:00 +0000]`))
|
req = regexpDate.ReplaceAllLiteral(req, []byte(`[ACME Challenge 01 Jan 16 00:00 +0000]`))
|
||||||
resp, ok := serverResponses[string(req)]
|
resp, ok := serverResponses[string(req)]
|
||||||
require.True(t, ok, "Server response for request not found")
|
require.True(t, ok, "Server response for request not found")
|
||||||
|
|
||||||
_, err = io.Copy(w, strings.NewReader(resp))
|
_, errS = io.Copy(w, strings.NewReader(resp))
|
||||||
require.NoError(t, err)
|
require.NoError(t, errS)
|
||||||
}))
|
}))
|
||||||
defer fakeServer.Close()
|
defer fakeServer.Close()
|
||||||
|
|
||||||
|
|
|
@ -24,16 +24,16 @@ func TestDNSProvider(t *testing.T) {
|
||||||
fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
require.Equal(t, "application/json", r.Header.Get("Content-Type"), "invalid content type")
|
require.Equal(t, "application/json", r.Header.Get("Content-Type"), "invalid content type")
|
||||||
|
|
||||||
req, err := ioutil.ReadAll(r.Body)
|
req, errS := ioutil.ReadAll(r.Body)
|
||||||
require.NoError(t, err)
|
require.NoError(t, errS)
|
||||||
|
|
||||||
req = regexpToken.ReplaceAllLiteral(req, []byte(`"rrset_values":["TOKEN"]`))
|
req = regexpToken.ReplaceAllLiteral(req, []byte(`"rrset_values":["TOKEN"]`))
|
||||||
|
|
||||||
resp, ok := serverResponses[string(req)]
|
resp, ok := serverResponses[string(req)]
|
||||||
require.True(t, ok, "Server response for request not found")
|
require.True(t, ok, "Server response for request not found")
|
||||||
|
|
||||||
_, err = io.Copy(w, strings.NewReader(resp))
|
_, errS = io.Copy(w, strings.NewReader(resp))
|
||||||
require.NoError(t, err)
|
require.NoError(t, errS)
|
||||||
}))
|
}))
|
||||||
defer fakeServer.Close()
|
defer fakeServer.Close()
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
return &DNSProvider{config: config, client: svc}, nil
|
return &DNSProvider{config: config, client: svc}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
// Present creates a TXT record to fulfill the dns-01 challenge.
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"golang.org/x/oauth2/google"
|
"golang.org/x/oauth2/google"
|
||||||
"google.golang.org/api/dns/v1"
|
"google.golang.org/api/dns/v1"
|
||||||
|
@ -39,7 +40,7 @@ func TestNewDNSProviderValid(t *testing.T) {
|
||||||
os.Setenv("GCE_PROJECT", "")
|
os.Setenv("GCE_PROJECT", "")
|
||||||
|
|
||||||
_, err := NewDNSProviderCredentials("my-project")
|
_, err := NewDNSProviderCredentials("my-project")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
|
@ -51,7 +52,7 @@ func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
os.Setenv("GCE_PROJECT", "my-project")
|
os.Setenv("GCE_PROJECT", "my-project")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||||
|
@ -68,10 +69,10 @@ func TestLiveGoogleCloudPresent(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, err := NewDNSProviderCredentials(gcloudProject)
|
provider, err := NewDNSProviderCredentials(gcloudProject)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.Present(gcloudDomain, "", "123d==")
|
err = provider.Present(gcloudDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLiveGoogleCloudPresentMultiple(t *testing.T) {
|
func TestLiveGoogleCloudPresentMultiple(t *testing.T) {
|
||||||
|
@ -80,13 +81,13 @@ func TestLiveGoogleCloudPresentMultiple(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, err := NewDNSProviderCredentials(gcloudProject)
|
provider, err := NewDNSProviderCredentials(gcloudProject)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Check that we're able to create multiple entries
|
// Check that we're able to create multiple entries
|
||||||
err = provider.Present(gcloudDomain, "1", "123d==")
|
err = provider.Present(gcloudDomain, "1", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = provider.Present(gcloudDomain, "2", "123d==")
|
err = provider.Present(gcloudDomain, "2", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLiveGoogleCloudCleanUp(t *testing.T) {
|
func TestLiveGoogleCloudCleanUp(t *testing.T) {
|
||||||
|
@ -97,8 +98,8 @@ func TestLiveGoogleCloudCleanUp(t *testing.T) {
|
||||||
time.Sleep(time.Second * 1)
|
time.Sleep(time.Second * 1)
|
||||||
|
|
||||||
provider, err := NewDNSProviderCredentials(gcloudProject)
|
provider, err := NewDNSProviderCredentials(gcloudProject)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.CleanUp(gcloudDomain, "", "123d==")
|
err = provider.CleanUp(gcloudDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,8 +160,6 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
// POSTing/Marshalling/Unmarshalling
|
|
||||||
|
|
||||||
func (d *DNSProvider) sendRequest(method string, resource string, payload interface{}) (*responseStruct, error) {
|
func (d *DNSProvider) sendRequest(method string, resource string, payload interface{}) (*responseStruct, error) {
|
||||||
url := fmt.Sprintf("%s/%s", defaultBaseURL, resource)
|
url := fmt.Sprintf("%s/%s", defaultBaseURL, resource)
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -41,10 +42,10 @@ func TestDNSProvider_Present(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.Present(glesysDomain, "", "123d==")
|
err = provider.Present(glesysDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDNSProvider_CleanUp(t *testing.T) {
|
func TestDNSProvider_CleanUp(t *testing.T) {
|
||||||
|
@ -53,8 +54,8 @@ func TestDNSProvider_CleanUp(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.CleanUp(glesysDomain, "", "123d==")
|
err = provider.CleanUp(glesysDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ func (d *DNSProvider) extractRecordName(fqdn, domain string) string {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge
|
// Present creates a TXT record to fulfill the dns-01 challenge
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
domainZone, err := d.getZone(fqdn)
|
domainZone, err := d.getZone(fqdn)
|
||||||
|
|
|
@ -89,7 +89,7 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge
|
// Present creates a TXT record to fulfill the dns-01 challenge
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
|
|
||||||
err := d.newTxtRecord(domain, fqdn, `"`+value+`"`)
|
err := d.newTxtRecord(fqdn, `"`+value+`"`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("lightsail: %v", err)
|
return fmt.Errorf("lightsail: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DNSProvider) newTxtRecord(domain string, fqdn string, value string) error {
|
func (d *DNSProvider) newTxtRecord(fqdn string, value string) error {
|
||||||
params := &lightsail.CreateDomainEntryInput{
|
params := &lightsail.CreateDomainEntryInput{
|
||||||
DomainName: aws.String(d.config.DNSZone),
|
DomainName: aws.String(d.config.DNSZone),
|
||||||
DomainEntry: &lightsail.DomainEntry{
|
DomainEntry: &lightsail.DomainEntry{
|
||||||
|
|
|
@ -20,41 +20,42 @@ func TestLightsailTTL(t *testing.T) {
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.Present(m["lightsailDomain"], "foo", "bar")
|
lightsailDomain := m["lightsailDomain"]
|
||||||
|
|
||||||
|
err = provider.Present(lightsailDomain, "foo", "bar")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// we need a separate Lightshail client here as the one in the DNS provider is
|
// we need a separate Lightshail client here as the one in the DNS provider is
|
||||||
// unexported.
|
// unexported.
|
||||||
fqdn := "_acme-challenge." + m["lightsailDomain"]
|
fqdn := "_acme-challenge." + lightsailDomain
|
||||||
sess, err := session.NewSession()
|
sess, err := session.NewSession()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
svc := lightsail.New(sess)
|
svc := lightsail.New(sess)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
provider.CleanUp(m["lightsailDomain"], "foo", "bar")
|
|
||||||
t.Fatal(err)
|
defer func() {
|
||||||
}
|
errC := provider.CleanUp(lightsailDomain, "foo", "bar")
|
||||||
|
if errC != nil {
|
||||||
|
t.Log(errC)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
params := &lightsail.GetDomainInput{
|
params := &lightsail.GetDomainInput{
|
||||||
DomainName: aws.String(m["lightsailDomain"]),
|
DomainName: aws.String(lightsailDomain),
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := svc.GetDomain(params)
|
resp, err := svc.GetDomain(params)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
provider.CleanUp(m["lightsailDomain"], "foo", "bar")
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
entries := resp.Domain.DomainEntries
|
entries := resp.Domain.DomainEntries
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
if *entry.Type == "TXT" && *entry.Name == fqdn {
|
if *entry.Type == "TXT" && *entry.Name == fqdn {
|
||||||
provider.CleanUp(m["lightsailDomain"], "foo", "bar")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
provider.CleanUp(m["lightsailDomain"], "foo", "bar")
|
t.Fatalf("Could not find a TXT record for _acme-challenge.%s", lightsailDomain)
|
||||||
t.Fatalf("Could not find a TXT record for _acme-challenge.%s", m["lightsailDomain"])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testGetAndPreCheck() (map[string]string, error) {
|
func testGetAndPreCheck() (map[string]string, error) {
|
||||||
|
|
|
@ -27,7 +27,11 @@ func newMockServer(t *testing.T, responses map[string]MockResponse) *httptest.Se
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/xml")
|
w.Header().Set("Content-Type", "application/xml")
|
||||||
w.WriteHeader(resp.StatusCode)
|
w.WriteHeader(resp.StatusCode)
|
||||||
w.Write([]byte(resp.Body))
|
_, err := w.Write([]byte(resp.Body))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
|
@ -48,7 +48,7 @@ func newMockServer(t *testing.T, responses MockResponseMap) *httptest.Server {
|
||||||
action := r.URL.Query().Get("api_action")
|
action := r.URL.Query().Get("api_action")
|
||||||
resp, ok := responses[action]
|
resp, ok := responses[action]
|
||||||
if !ok {
|
if !ok {
|
||||||
require.FailNowf(t, "Unsupported mock action: %s", action)
|
require.FailNowf(t, "Unsupported mock action: %q", action)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the response that the server will return.
|
// Build the response that the server will return.
|
||||||
|
@ -66,7 +66,11 @@ func newMockServer(t *testing.T, responses MockResponseMap) *httptest.Server {
|
||||||
// Send the response.
|
// Send the response.
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write(rawResponse)
|
_, err = w.Write(rawResponse)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
@ -78,7 +82,7 @@ func TestNewDNSProviderWithEnv(t *testing.T) {
|
||||||
os.Setenv("LINODE_API_KEY", "testing")
|
os.Setenv("LINODE_API_KEY", "testing")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderWithoutEnv(t *testing.T) {
|
func TestNewDNSProviderWithoutEnv(t *testing.T) {
|
||||||
|
@ -89,15 +93,15 @@ func TestNewDNSProviderWithoutEnv(t *testing.T) {
|
||||||
assert.EqualError(t, err, "linode: some credentials information are missing: LINODE_API_KEY")
|
assert.EqualError(t, err, "linode: some credentials information are missing: LINODE_API_KEY")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderCredentialsWithKey(t *testing.T) {
|
func TestNewDNSProviderWithKey(t *testing.T) {
|
||||||
config := NewDefaultConfig()
|
config := NewDefaultConfig()
|
||||||
config.APIKey = "testing"
|
config.APIKey = "testing"
|
||||||
|
|
||||||
_, err := NewDNSProviderConfig(config)
|
_, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderCredentialsWithoutKey(t *testing.T) {
|
func TestNewDNSProviderWithoutKey(t *testing.T) {
|
||||||
config := NewDefaultConfig()
|
config := NewDefaultConfig()
|
||||||
|
|
||||||
_, err := NewDNSProviderConfig(config)
|
_, err := NewDNSProviderConfig(config)
|
||||||
|
@ -109,105 +113,94 @@ func TestDNSProvider_Present(t *testing.T) {
|
||||||
os.Setenv("LINODE_API_KEY", "testing")
|
os.Setenv("LINODE_API_KEY", "testing")
|
||||||
|
|
||||||
p, err := NewDNSProvider()
|
p, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
domain := "example.com"
|
domain := "example.com"
|
||||||
keyAuth := "dGVzdGluZw=="
|
keyAuth := "dGVzdGluZw=="
|
||||||
mockResponses := MockResponseMap{
|
|
||||||
"domain.list": MockResponse{
|
testCases := []struct {
|
||||||
Response: []dns.Domain{
|
desc string
|
||||||
{
|
mockResponses MockResponseMap
|
||||||
Domain: domain,
|
expectedError string
|
||||||
DomainID: 1234,
|
}{
|
||||||
|
{
|
||||||
|
desc: "success",
|
||||||
|
mockResponses: MockResponseMap{
|
||||||
|
"domain.list": MockResponse{
|
||||||
|
Response: []dns.Domain{
|
||||||
|
{
|
||||||
|
Domain: domain,
|
||||||
|
DomainID: 1234,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"domain.resource.create": MockResponse{
|
||||||
|
Response: dns.ResourceResponse{
|
||||||
|
ResourceID: 1234,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"domain.resource.create": MockResponse{
|
{
|
||||||
Response: dns.ResourceResponse{
|
desc: "NoDomain",
|
||||||
ResourceID: 1234,
|
mockResponses: MockResponseMap{
|
||||||
|
"domain.list": MockResponse{
|
||||||
|
Response: []dns.Domain{{
|
||||||
|
Domain: "foobar.com",
|
||||||
|
DomainID: 1234,
|
||||||
|
}},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
expectedError: "dns: requested domain not found",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "CreateFailed",
|
||||||
|
mockResponses: MockResponseMap{
|
||||||
|
"domain.list": MockResponse{
|
||||||
|
Response: []dns.Domain{
|
||||||
|
{
|
||||||
|
Domain: domain,
|
||||||
|
DomainID: 1234,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"domain.resource.create": MockResponse{
|
||||||
|
Response: nil,
|
||||||
|
Errors: []linode.ResponseError{
|
||||||
|
{
|
||||||
|
Code: 1234,
|
||||||
|
Message: "Failed to create domain resource",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedError: "Failed to create domain resource",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
for _, test := range testCases {
|
||||||
defer mockSrv.Close()
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
|
||||||
p.client.ToLinode().SetEndpoint(mockSrv.URL)
|
mockSrv := newMockServer(t, test.mockResponses)
|
||||||
|
defer mockSrv.Close()
|
||||||
|
|
||||||
err = p.Present(domain, "", keyAuth)
|
p.client.ToLinode().SetEndpoint(mockSrv.URL)
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDNSProvider_PresentNoDomain(t *testing.T) {
|
err = p.Present(domain, "", keyAuth)
|
||||||
defer restoreEnv()
|
if len(test.expectedError) == 0 {
|
||||||
os.Setenv("LINODE_API_KEY", "testing")
|
assert.NoError(t, err)
|
||||||
|
} else {
|
||||||
p, err := NewDNSProvider()
|
assert.EqualError(t, err, test.expectedError)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
|
})
|
||||||
domain := "example.com"
|
|
||||||
keyAuth := "dGVzdGluZw=="
|
|
||||||
mockResponses := MockResponseMap{
|
|
||||||
"domain.list": MockResponse{
|
|
||||||
Response: []dns.Domain{
|
|
||||||
{
|
|
||||||
Domain: "foobar.com",
|
|
||||||
DomainID: 1234,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
|
||||||
defer mockSrv.Close()
|
|
||||||
|
|
||||||
p.client.ToLinode().SetEndpoint(mockSrv.URL)
|
|
||||||
|
|
||||||
err = p.Present(domain, "", keyAuth)
|
|
||||||
assert.EqualError(t, err, "dns: requested domain not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDNSProvider_PresentCreateFailed(t *testing.T) {
|
|
||||||
defer restoreEnv()
|
|
||||||
os.Setenv("LINODE_API_KEY", "testing")
|
|
||||||
|
|
||||||
p, err := NewDNSProvider()
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
domain := "example.com"
|
|
||||||
keyAuth := "dGVzdGluZw=="
|
|
||||||
mockResponses := MockResponseMap{
|
|
||||||
"domain.list": MockResponse{
|
|
||||||
Response: []dns.Domain{
|
|
||||||
{
|
|
||||||
Domain: domain,
|
|
||||||
DomainID: 1234,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"domain.resource.create": MockResponse{
|
|
||||||
Response: nil,
|
|
||||||
Errors: []linode.ResponseError{
|
|
||||||
{
|
|
||||||
Code: 1234,
|
|
||||||
Message: "Failed to create domain resource",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
|
||||||
defer mockSrv.Close()
|
|
||||||
|
|
||||||
p.client.ToLinode().SetEndpoint(mockSrv.URL)
|
|
||||||
|
|
||||||
err = p.Present(domain, "", keyAuth)
|
|
||||||
assert.EqualError(t, err, "Failed to create domain resource")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDNSProvider_PresentLive(t *testing.T) {
|
func TestDNSProvider_PresentLive(t *testing.T) {
|
||||||
if !isTestLive {
|
if !isTestLive {
|
||||||
t.Skip("Skipping live test")
|
t.Skip("Skipping live test")
|
||||||
}
|
}
|
||||||
|
// TODO implement this test
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDNSProvider_CleanUp(t *testing.T) {
|
func TestDNSProvider_CleanUp(t *testing.T) {
|
||||||
|
@ -215,120 +208,108 @@ func TestDNSProvider_CleanUp(t *testing.T) {
|
||||||
os.Setenv("LINODE_API_KEY", "testing")
|
os.Setenv("LINODE_API_KEY", "testing")
|
||||||
|
|
||||||
p, err := NewDNSProvider()
|
p, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
domain := "example.com"
|
domain := "example.com"
|
||||||
keyAuth := "dGVzdGluZw=="
|
keyAuth := "dGVzdGluZw=="
|
||||||
mockResponses := MockResponseMap{
|
|
||||||
"domain.list": MockResponse{
|
testCases := []struct {
|
||||||
Response: []dns.Domain{
|
desc string
|
||||||
{
|
mockResponses MockResponseMap
|
||||||
Domain: domain,
|
expectedError string
|
||||||
DomainID: 1234,
|
}{
|
||||||
|
{
|
||||||
|
desc: "success",
|
||||||
|
mockResponses: MockResponseMap{
|
||||||
|
"domain.list": MockResponse{
|
||||||
|
Response: []dns.Domain{
|
||||||
|
{
|
||||||
|
Domain: domain,
|
||||||
|
DomainID: 1234,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"domain.resource.list": MockResponse{
|
||||||
|
Response: []dns.Resource{
|
||||||
|
{
|
||||||
|
DomainID: 1234,
|
||||||
|
Name: "_acme-challenge",
|
||||||
|
ResourceID: 1234,
|
||||||
|
Target: "ElbOJKOkFWiZLQeoxf-wb3IpOsQCdvoM0y_wn0TEkxM",
|
||||||
|
Type: "TXT",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"domain.resource.delete": MockResponse{
|
||||||
|
Response: dns.ResourceResponse{
|
||||||
|
ResourceID: 1234,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"domain.resource.list": MockResponse{
|
{
|
||||||
Response: []dns.Resource{
|
desc: "NoDomain",
|
||||||
{
|
mockResponses: MockResponseMap{
|
||||||
DomainID: 1234,
|
"domain.list": MockResponse{
|
||||||
Name: "_acme-challenge",
|
Response: []dns.Domain{
|
||||||
ResourceID: 1234,
|
{
|
||||||
Target: "ElbOJKOkFWiZLQeoxf-wb3IpOsQCdvoM0y_wn0TEkxM",
|
Domain: "foobar.com",
|
||||||
Type: "TXT",
|
DomainID: 1234,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
expectedError: "dns: requested domain not found",
|
||||||
},
|
},
|
||||||
"domain.resource.delete": MockResponse{
|
{
|
||||||
Response: dns.ResourceResponse{
|
desc: "DeleteFailed",
|
||||||
ResourceID: 1234,
|
mockResponses: MockResponseMap{
|
||||||
|
"domain.list": MockResponse{
|
||||||
|
Response: []dns.Domain{
|
||||||
|
{
|
||||||
|
Domain: domain,
|
||||||
|
DomainID: 1234,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"domain.resource.list": MockResponse{
|
||||||
|
Response: []dns.Resource{
|
||||||
|
{
|
||||||
|
DomainID: 1234,
|
||||||
|
Name: "_acme-challenge",
|
||||||
|
ResourceID: 1234,
|
||||||
|
Target: "ElbOJKOkFWiZLQeoxf-wb3IpOsQCdvoM0y_wn0TEkxM",
|
||||||
|
Type: "TXT",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"domain.resource.delete": MockResponse{
|
||||||
|
Response: nil,
|
||||||
|
Errors: []linode.ResponseError{
|
||||||
|
{
|
||||||
|
Code: 1234,
|
||||||
|
Message: "Failed to delete domain resource",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
expectedError: "Failed to delete domain resource",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
for _, test := range testCases {
|
||||||
defer mockSrv.Close()
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
mockSrv := newMockServer(t, test.mockResponses)
|
||||||
|
defer mockSrv.Close()
|
||||||
|
|
||||||
p.client.ToLinode().SetEndpoint(mockSrv.URL)
|
p.client.ToLinode().SetEndpoint(mockSrv.URL)
|
||||||
|
|
||||||
err = p.CleanUp(domain, "", keyAuth)
|
err = p.CleanUp(domain, "", keyAuth)
|
||||||
assert.NoError(t, err)
|
if len(test.expectedError) == 0 {
|
||||||
}
|
assert.NoError(t, err)
|
||||||
|
} else {
|
||||||
func TestDNSProvider_CleanUpNoDomain(t *testing.T) {
|
assert.EqualError(t, err, test.expectedError)
|
||||||
defer restoreEnv()
|
}
|
||||||
os.Setenv("LINODE_API_KEY", "testing")
|
})
|
||||||
|
|
||||||
p, err := NewDNSProvider()
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
domain := "example.com"
|
|
||||||
keyAuth := "dGVzdGluZw=="
|
|
||||||
mockResponses := MockResponseMap{
|
|
||||||
"domain.list": MockResponse{
|
|
||||||
Response: []dns.Domain{
|
|
||||||
{
|
|
||||||
Domain: "foobar.com",
|
|
||||||
DomainID: 1234,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
|
||||||
defer mockSrv.Close()
|
|
||||||
|
|
||||||
p.client.ToLinode().SetEndpoint(mockSrv.URL)
|
|
||||||
|
|
||||||
err = p.CleanUp(domain, "", keyAuth)
|
|
||||||
assert.EqualError(t, err, "dns: requested domain not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDNSProvider_CleanUpDeleteFailed(t *testing.T) {
|
|
||||||
defer restoreEnv()
|
|
||||||
os.Setenv("LINODE_API_KEY", "testing")
|
|
||||||
|
|
||||||
p, err := NewDNSProvider()
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
domain := "example.com"
|
|
||||||
keyAuth := "dGVzdGluZw=="
|
|
||||||
mockResponses := MockResponseMap{
|
|
||||||
"domain.list": MockResponse{
|
|
||||||
Response: []dns.Domain{
|
|
||||||
{
|
|
||||||
Domain: domain,
|
|
||||||
DomainID: 1234,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"domain.resource.list": MockResponse{
|
|
||||||
Response: []dns.Resource{
|
|
||||||
{
|
|
||||||
DomainID: 1234,
|
|
||||||
Name: "_acme-challenge",
|
|
||||||
ResourceID: 1234,
|
|
||||||
Target: "ElbOJKOkFWiZLQeoxf-wb3IpOsQCdvoM0y_wn0TEkxM",
|
|
||||||
Type: "TXT",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"domain.resource.delete": MockResponse{
|
|
||||||
Response: nil,
|
|
||||||
Errors: []linode.ResponseError{
|
|
||||||
{
|
|
||||||
Code: 1234,
|
|
||||||
Message: "Failed to delete domain resource",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
|
||||||
defer mockSrv.Close()
|
|
||||||
|
|
||||||
p.client.ToLinode().SetEndpoint(mockSrv.URL)
|
|
||||||
|
|
||||||
err = p.CleanUp(domain, "", keyAuth)
|
|
||||||
assert.EqualError(t, err, "Failed to delete domain resource")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,12 +83,12 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
linodeClient := linodego.NewClient(oauth2Client)
|
client := linodego.NewClient(oauth2Client)
|
||||||
linodeClient.SetUserAgent(fmt.Sprintf("lego-dns linodego/%s", linodego.Version))
|
client.SetUserAgent(fmt.Sprintf("lego-dns linodego/%s", linodego.Version))
|
||||||
|
|
||||||
return &DNSProvider{
|
return &DNSProvider{
|
||||||
config: config,
|
config: config,
|
||||||
client: &linodeClient,
|
client: &client,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,11 @@ func newMockServer(t *testing.T, responses MockResponseMap) *httptest.Server {
|
||||||
} else {
|
} else {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
}
|
}
|
||||||
w.Write(rawResponse)
|
|
||||||
|
_, err = w.Write(rawResponse)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
@ -81,7 +85,7 @@ func TestNewDNSProviderWithoutEnv(t *testing.T) {
|
||||||
assert.EqualError(t, err, "linodev4: some credentials information are missing: LINODE_TOKEN")
|
assert.EqualError(t, err, "linodev4: some credentials information are missing: LINODE_TOKEN")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderCredentialsWithKey(t *testing.T) {
|
func TestNewDNSProviderWithKey(t *testing.T) {
|
||||||
config := NewDefaultConfig()
|
config := NewDefaultConfig()
|
||||||
config.Token = "testing"
|
config.Token = "testing"
|
||||||
|
|
||||||
|
@ -89,7 +93,7 @@ func TestNewDNSProviderCredentialsWithKey(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderCredentialsWithoutKey(t *testing.T) {
|
func TestNewDNSProviderWithoutKey(t *testing.T) {
|
||||||
config := NewDefaultConfig()
|
config := NewDefaultConfig()
|
||||||
config.Token = ""
|
config.Token = ""
|
||||||
|
|
||||||
|
@ -102,104 +106,96 @@ func TestDNSProvider_Present(t *testing.T) {
|
||||||
os.Setenv("LINODE_TOKEN", "testing")
|
os.Setenv("LINODE_TOKEN", "testing")
|
||||||
|
|
||||||
p, err := NewDNSProvider()
|
p, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, p)
|
||||||
|
|
||||||
domain := "example.com"
|
domain := "example.com"
|
||||||
keyAuth := "dGVzdGluZw=="
|
keyAuth := "dGVzdGluZw=="
|
||||||
|
|
||||||
mockResponses := MockResponseMap{
|
testCases := []struct {
|
||||||
"GET:/domains": linodego.DomainsPagedResponse{
|
desc string
|
||||||
PageOptions: &linodego.PageOptions{
|
mockResponses MockResponseMap
|
||||||
Pages: 1,
|
expectedError string
|
||||||
Results: 1,
|
}{
|
||||||
Page: 1,
|
{
|
||||||
|
desc: "Success",
|
||||||
|
mockResponses: MockResponseMap{
|
||||||
|
"GET:/domains": linodego.DomainsPagedResponse{
|
||||||
|
PageOptions: &linodego.PageOptions{
|
||||||
|
Pages: 1,
|
||||||
|
Results: 1,
|
||||||
|
Page: 1,
|
||||||
|
},
|
||||||
|
Data: []linodego.Domain{{
|
||||||
|
Domain: domain,
|
||||||
|
ID: 1234,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
"POST:/domains/1234/records": linodego.DomainRecord{
|
||||||
|
ID: 1234,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Data: []linodego.Domain{{
|
|
||||||
Domain: domain,
|
|
||||||
ID: 1234,
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
"POST:/domains/1234/records": linodego.DomainRecord{
|
{
|
||||||
ID: 1234,
|
desc: "NoDomain",
|
||||||
},
|
mockResponses: MockResponseMap{
|
||||||
}
|
"GET:/domains": linodego.APIError{
|
||||||
|
Errors: []linodego.APIErrorReason{{
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
Reason: "Not found",
|
||||||
defer mockSrv.Close()
|
}},
|
||||||
|
},
|
||||||
p.client.SetBaseURL(mockSrv.URL)
|
|
||||||
|
|
||||||
err = p.Present(domain, "", keyAuth)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDNSProvider_PresentNoDomain(t *testing.T) {
|
|
||||||
defer restoreEnv()
|
|
||||||
os.Setenv("LINODE_TOKEN", "testing")
|
|
||||||
|
|
||||||
p, err := NewDNSProvider()
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
domain := "example.com"
|
|
||||||
keyAuth := "dGVzdGluZw=="
|
|
||||||
mockResponses := MockResponseMap{
|
|
||||||
"GET:/domains": linodego.APIError{
|
|
||||||
Errors: []linodego.APIErrorReason{{
|
|
||||||
Reason: "Not found",
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
|
||||||
defer mockSrv.Close()
|
|
||||||
|
|
||||||
p.client.SetBaseURL(mockSrv.URL)
|
|
||||||
|
|
||||||
err = p.Present(domain, "", keyAuth)
|
|
||||||
assert.EqualError(t, err, "[404] Not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDNSProvider_PresentCreateFailed(t *testing.T) {
|
|
||||||
defer restoreEnv()
|
|
||||||
os.Setenv("LINODE_TOKEN", "testing")
|
|
||||||
|
|
||||||
p, err := NewDNSProvider()
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
domain := "example.com"
|
|
||||||
keyAuth := "dGVzdGluZw=="
|
|
||||||
mockResponses := MockResponseMap{
|
|
||||||
"GET:/domains": &linodego.DomainsPagedResponse{
|
|
||||||
PageOptions: &linodego.PageOptions{
|
|
||||||
Pages: 1,
|
|
||||||
Results: 1,
|
|
||||||
Page: 1,
|
|
||||||
},
|
},
|
||||||
Data: []linodego.Domain{{
|
expectedError: "[404] Not found",
|
||||||
Domain: "foobar.com",
|
|
||||||
ID: 1234,
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
"POST:/domains/1234/records": linodego.APIError{
|
{
|
||||||
Errors: []linodego.APIErrorReason{{
|
desc: "CreateFailed",
|
||||||
Reason: "Failed to create domain resource",
|
mockResponses: MockResponseMap{
|
||||||
Field: "somefield",
|
"GET:/domains": &linodego.DomainsPagedResponse{
|
||||||
}},
|
PageOptions: &linodego.PageOptions{
|
||||||
|
Pages: 1,
|
||||||
|
Results: 1,
|
||||||
|
Page: 1,
|
||||||
|
},
|
||||||
|
Data: []linodego.Domain{{
|
||||||
|
Domain: "foobar.com",
|
||||||
|
ID: 1234,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
"POST:/domains/1234/records": linodego.APIError{
|
||||||
|
Errors: []linodego.APIErrorReason{{
|
||||||
|
Reason: "Failed to create domain resource",
|
||||||
|
Field: "somefield",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedError: "[400] [somefield] Failed to create domain resource",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
|
||||||
defer mockSrv.Close()
|
|
||||||
|
|
||||||
p.client.SetBaseURL(mockSrv.URL)
|
for _, test := range testCases {
|
||||||
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
|
||||||
err = p.Present(domain, "", keyAuth)
|
mockSrv := newMockServer(t, test.mockResponses)
|
||||||
assert.EqualError(t, err, "[400] [somefield] Failed to create domain resource")
|
defer mockSrv.Close()
|
||||||
|
|
||||||
|
assert.NotNil(t, p.client)
|
||||||
|
p.client.SetBaseURL(mockSrv.URL)
|
||||||
|
|
||||||
|
err = p.Present(domain, "", keyAuth)
|
||||||
|
if len(test.expectedError) == 0 {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
} else {
|
||||||
|
assert.EqualError(t, err, test.expectedError)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDNSProvider_PresentLive(t *testing.T) {
|
func TestDNSProvider_PresentLive(t *testing.T) {
|
||||||
if !isTestLive {
|
if !isTestLive {
|
||||||
t.Skip("Skipping live test")
|
t.Skip("Skipping live test")
|
||||||
}
|
}
|
||||||
|
// TODO implement this test
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDNSProvider_CleanUp(t *testing.T) {
|
func TestDNSProvider_CleanUp(t *testing.T) {
|
||||||
|
@ -207,124 +203,112 @@ func TestDNSProvider_CleanUp(t *testing.T) {
|
||||||
os.Setenv("LINODE_TOKEN", "testing")
|
os.Setenv("LINODE_TOKEN", "testing")
|
||||||
|
|
||||||
p, err := NewDNSProvider()
|
p, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
domain := "example.com"
|
domain := "example.com"
|
||||||
keyAuth := "dGVzdGluZw=="
|
keyAuth := "dGVzdGluZw=="
|
||||||
mockResponses := MockResponseMap{
|
|
||||||
"GET:/domains": &linodego.DomainsPagedResponse{
|
testCases := []struct {
|
||||||
PageOptions: &linodego.PageOptions{
|
desc string
|
||||||
Pages: 1,
|
mockResponses MockResponseMap
|
||||||
Results: 1,
|
expectedError string
|
||||||
Page: 1,
|
}{
|
||||||
|
{
|
||||||
|
desc: "Success",
|
||||||
|
mockResponses: MockResponseMap{
|
||||||
|
"GET:/domains": &linodego.DomainsPagedResponse{
|
||||||
|
PageOptions: &linodego.PageOptions{
|
||||||
|
Pages: 1,
|
||||||
|
Results: 1,
|
||||||
|
Page: 1,
|
||||||
|
},
|
||||||
|
Data: []linodego.Domain{{
|
||||||
|
Domain: "foobar.com",
|
||||||
|
ID: 1234,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
"GET:/domains/1234/records": &linodego.DomainRecordsPagedResponse{
|
||||||
|
PageOptions: &linodego.PageOptions{
|
||||||
|
Pages: 1,
|
||||||
|
Results: 1,
|
||||||
|
Page: 1,
|
||||||
|
},
|
||||||
|
Data: []linodego.DomainRecord{{
|
||||||
|
ID: 1234,
|
||||||
|
Name: "_acme-challenge",
|
||||||
|
Target: "ElbOJKOkFWiZLQeoxf-wb3IpOsQCdvoM0y_wn0TEkxM",
|
||||||
|
Type: "TXT",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
"DELETE:/domains/1234/records/1234": struct{}{},
|
||||||
},
|
},
|
||||||
Data: []linodego.Domain{{
|
|
||||||
Domain: "foobar.com",
|
|
||||||
ID: 1234,
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
"GET:/domains/1234/records": &linodego.DomainRecordsPagedResponse{
|
{
|
||||||
PageOptions: &linodego.PageOptions{
|
desc: "NoDomain",
|
||||||
Pages: 1,
|
mockResponses: MockResponseMap{
|
||||||
Results: 1,
|
"GET:/domains": linodego.APIError{
|
||||||
Page: 1,
|
Errors: []linodego.APIErrorReason{{
|
||||||
|
Reason: "Not found",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
"GET:/domains/1234/records": linodego.APIError{
|
||||||
|
Errors: []linodego.APIErrorReason{{
|
||||||
|
Reason: "Not found",
|
||||||
|
}},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Data: []linodego.DomainRecord{{
|
expectedError: "[404] Not found",
|
||||||
ID: 1234,
|
|
||||||
Name: "_acme-challenge",
|
|
||||||
Target: "ElbOJKOkFWiZLQeoxf-wb3IpOsQCdvoM0y_wn0TEkxM",
|
|
||||||
Type: "TXT",
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
"DELETE:/domains/1234/records/1234": struct{}{},
|
{
|
||||||
}
|
desc: "DeleteFailed",
|
||||||
|
mockResponses: MockResponseMap{
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
"GET:/domains": linodego.DomainsPagedResponse{
|
||||||
defer mockSrv.Close()
|
PageOptions: &linodego.PageOptions{
|
||||||
|
Pages: 1,
|
||||||
p.client.SetBaseURL(mockSrv.URL)
|
Results: 1,
|
||||||
|
Page: 1,
|
||||||
err = p.CleanUp(domain, "", keyAuth)
|
},
|
||||||
assert.NoError(t, err)
|
Data: []linodego.Domain{{
|
||||||
}
|
ID: 1234,
|
||||||
|
Domain: "example.com",
|
||||||
func TestDNSProvider_CleanUpNoDomain(t *testing.T) {
|
}},
|
||||||
defer restoreEnv()
|
},
|
||||||
os.Setenv("LINODE_TOKEN", "testing")
|
"GET:/domains/1234/records": linodego.DomainRecordsPagedResponse{
|
||||||
|
PageOptions: &linodego.PageOptions{
|
||||||
p, err := NewDNSProvider()
|
Pages: 1,
|
||||||
assert.NoError(t, err)
|
Results: 1,
|
||||||
|
Page: 1,
|
||||||
domain := "example.com"
|
},
|
||||||
keyAuth := "dGVzdGluZw=="
|
Data: []linodego.DomainRecord{{
|
||||||
mockResponses := MockResponseMap{
|
ID: 1234,
|
||||||
"GET:/domains": linodego.APIError{
|
Name: "_acme-challenge",
|
||||||
Errors: []linodego.APIErrorReason{{
|
Target: "ElbOJKOkFWiZLQeoxf-wb3IpOsQCdvoM0y_wn0TEkxM",
|
||||||
Reason: "Not found",
|
Type: "TXT",
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
"GET:/domains/1234/records": linodego.APIError{
|
"DELETE:/domains/1234/records/1234": linodego.APIError{
|
||||||
Errors: []linodego.APIErrorReason{{
|
Errors: []linodego.APIErrorReason{{
|
||||||
Reason: "Not found",
|
Reason: "Failed to delete domain resource",
|
||||||
}},
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedError: "[400] Failed to delete domain resource",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
for _, test := range testCases {
|
||||||
defer mockSrv.Close()
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
mockSrv := newMockServer(t, test.mockResponses)
|
||||||
|
defer mockSrv.Close()
|
||||||
|
|
||||||
p.client.SetBaseURL(mockSrv.URL)
|
p.client.SetBaseURL(mockSrv.URL)
|
||||||
|
|
||||||
err = p.CleanUp(domain, "", keyAuth)
|
err = p.CleanUp(domain, "", keyAuth)
|
||||||
assert.EqualError(t, err, "[404] Not found")
|
if len(test.expectedError) == 0 {
|
||||||
}
|
assert.NoError(t, err)
|
||||||
|
} else {
|
||||||
func TestDNSProvider_CleanUpDeleteFailed(t *testing.T) {
|
assert.EqualError(t, err, test.expectedError)
|
||||||
defer restoreEnv()
|
}
|
||||||
os.Setenv("LINODE_TOKEN", "testing")
|
})
|
||||||
|
|
||||||
p, err := NewDNSProvider()
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
domain := "example.com"
|
|
||||||
keyAuth := "dGVzdGluZw=="
|
|
||||||
mockResponses := MockResponseMap{
|
|
||||||
"GET:/domains": linodego.DomainsPagedResponse{
|
|
||||||
PageOptions: &linodego.PageOptions{
|
|
||||||
Pages: 1,
|
|
||||||
Results: 1,
|
|
||||||
Page: 1,
|
|
||||||
},
|
|
||||||
Data: []linodego.Domain{{
|
|
||||||
ID: 1234,
|
|
||||||
Domain: "example.com",
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
"GET:/domains/1234/records": linodego.DomainRecordsPagedResponse{
|
|
||||||
PageOptions: &linodego.PageOptions{
|
|
||||||
Pages: 1,
|
|
||||||
Results: 1,
|
|
||||||
Page: 1,
|
|
||||||
},
|
|
||||||
Data: []linodego.DomainRecord{{
|
|
||||||
ID: 1234,
|
|
||||||
Name: "_acme-challenge",
|
|
||||||
Target: "ElbOJKOkFWiZLQeoxf-wb3IpOsQCdvoM0y_wn0TEkxM",
|
|
||||||
Type: "TXT",
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
"DELETE:/domains/1234/records/1234": linodego.APIError{
|
|
||||||
Errors: []linodego.APIErrorReason{{
|
|
||||||
Reason: "Failed to delete domain resource",
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mockSrv := newMockServer(t, mockResponses)
|
|
||||||
defer mockSrv.Close()
|
|
||||||
|
|
||||||
p.client.SetBaseURL(mockSrv.URL)
|
|
||||||
|
|
||||||
err = p.CleanUp(domain, "", keyAuth)
|
|
||||||
assert.EqualError(t, err, "[400] Failed to delete domain resource")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,10 @@ package namecheap
|
||||||
|
|
||||||
import "encoding/xml"
|
import "encoding/xml"
|
||||||
|
|
||||||
// host describes a DNS record returned by the Namecheap DNS gethosts API.
|
// record describes a DNS record returned by the Namecheap DNS gethosts API.
|
||||||
// Namecheap uses the term "host" to refer to all DNS records that include
|
// Namecheap uses the term "host" to refer to all DNS records that include
|
||||||
// a host field (A, AAAA, CNAME, NS, TXT, URL).
|
// a host field (A, AAAA, CNAME, NS, TXT, URL).
|
||||||
type host struct {
|
type record struct {
|
||||||
Type string `xml:",attr"`
|
Type string `xml:",attr"`
|
||||||
Name string `xml:",attr"`
|
Name string `xml:",attr"`
|
||||||
Address string `xml:",attr"`
|
Address string `xml:",attr"`
|
||||||
|
@ -32,7 +32,7 @@ type getHostsResponse struct {
|
||||||
XMLName xml.Name `xml:"ApiResponse"`
|
XMLName xml.Name `xml:"ApiResponse"`
|
||||||
Status string `xml:"Status,attr"`
|
Status string `xml:"Status,attr"`
|
||||||
Errors []apierror `xml:"Errors>Error"`
|
Errors []apierror `xml:"Errors>Error"`
|
||||||
Hosts []host `xml:"CommandResponse>DomainDNSGetHostsResult>host"`
|
Hosts []record `xml:"CommandResponse>DomainDNSGetHostsResult>host"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type getTldsResponse struct {
|
type getTldsResponse struct {
|
||||||
|
|
|
@ -308,7 +308,7 @@ func (d *DNSProvider) getTLDs() (tlds map[string]string, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// getHosts reads the full list of DNS host records using the Namecheap API.
|
// getHosts reads the full list of DNS host records using the Namecheap API.
|
||||||
func (d *DNSProvider) getHosts(ch *challenge) (hosts []host, err error) {
|
func (d *DNSProvider) getHosts(ch *challenge) (hosts []record, err error) {
|
||||||
values := make(url.Values)
|
values := make(url.Values)
|
||||||
d.setGlobalParams(&values, "namecheap.domains.dns.getHosts")
|
d.setGlobalParams(&values, "namecheap.domains.dns.getHosts")
|
||||||
|
|
||||||
|
@ -348,7 +348,7 @@ func (d *DNSProvider) getHosts(ch *challenge) (hosts []host, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// setHosts writes the full list of DNS host records using the Namecheap API.
|
// setHosts writes the full list of DNS host records using the Namecheap API.
|
||||||
func (d *DNSProvider) setHosts(ch *challenge, hosts []host) error {
|
func (d *DNSProvider) setHosts(ch *challenge, hosts []record) error {
|
||||||
values := make(url.Values)
|
values := make(url.Values)
|
||||||
d.setGlobalParams(&values, "namecheap.domains.dns.setHosts")
|
d.setGlobalParams(&values, "namecheap.domains.dns.setHosts")
|
||||||
|
|
||||||
|
@ -395,8 +395,8 @@ func (d *DNSProvider) setHosts(ch *challenge, hosts []host) error {
|
||||||
|
|
||||||
// addChallengeRecord adds a DNS challenge TXT record to a list of namecheap
|
// addChallengeRecord adds a DNS challenge TXT record to a list of namecheap
|
||||||
// host records.
|
// host records.
|
||||||
func (d *DNSProvider) addChallengeRecord(ch *challenge, hosts *[]host) {
|
func (d *DNSProvider) addChallengeRecord(ch *challenge, hosts *[]record) {
|
||||||
host := host{
|
host := record{
|
||||||
Name: ch.key,
|
Name: ch.key,
|
||||||
Type: "TXT",
|
Type: "TXT",
|
||||||
Address: ch.keyValue,
|
Address: ch.keyValue,
|
||||||
|
@ -418,7 +418,7 @@ func (d *DNSProvider) addChallengeRecord(ch *challenge, hosts *[]host) {
|
||||||
|
|
||||||
// removeChallengeRecord removes a DNS challenge TXT record from a list of
|
// removeChallengeRecord removes a DNS challenge TXT record from a list of
|
||||||
// namecheap host records. Return true if a record was removed.
|
// namecheap host records. Return true if a record was removed.
|
||||||
func (d *DNSProvider) removeChallengeRecord(ch *challenge, hosts *[]host) bool {
|
func (d *DNSProvider) removeChallengeRecord(ch *challenge, hosts *[]record) bool {
|
||||||
// Find the challenge TXT record and remove it if found.
|
// Find the challenge TXT record and remove it if found.
|
||||||
for i, h := range *hosts {
|
for i, h := range *hosts {
|
||||||
if h.Name == ch.key && h.Type == "TXT" {
|
if h.Name == ch.key && h.Type == "TXT" {
|
||||||
|
|
|
@ -93,14 +93,14 @@ func TestSetHosts(t *testing.T) {
|
||||||
if test.errString != "" {
|
if test.errString != "" {
|
||||||
assert.EqualError(t, err, test.errString)
|
assert.EqualError(t, err, test.errString)
|
||||||
} else {
|
} else {
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = prov.setHosts(ch, hosts)
|
err = prov.setHosts(ch, hosts)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,7 +232,11 @@ func mockServer(tc *testcase, t *testing.T, w http.ResponseWriter, r *http.Reque
|
||||||
}
|
}
|
||||||
|
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
r.ParseForm()
|
err := r.ParseForm()
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
values := r.Form
|
values := r.Form
|
||||||
cmd := values.Get("Command")
|
cmd := values.Get("Command")
|
||||||
switch cmd {
|
switch cmd {
|
||||||
|
@ -246,7 +250,6 @@ func mockServer(tc *testcase, t *testing.T, w http.ResponseWriter, r *http.Reque
|
||||||
|
|
||||||
default:
|
default:
|
||||||
t.Errorf("Unexpected http method: %s", r.Method)
|
t.Errorf("Unexpected http method: %s", r.Method)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,7 +268,7 @@ func mockDNSProvider(url string) *DNSProvider {
|
||||||
type testcase struct {
|
type testcase struct {
|
||||||
name string
|
name string
|
||||||
domain string
|
domain string
|
||||||
hosts []host
|
hosts []record
|
||||||
errString string
|
errString string
|
||||||
getHostsResponse string
|
getHostsResponse string
|
||||||
setHostsResponse string
|
setHostsResponse string
|
||||||
|
@ -275,7 +278,7 @@ var testcases = []testcase{
|
||||||
{
|
{
|
||||||
name: "Test:Success:1",
|
name: "Test:Success:1",
|
||||||
domain: "test.example.com",
|
domain: "test.example.com",
|
||||||
hosts: []host{
|
hosts: []record{
|
||||||
{Type: "A", Name: "home", Address: "10.0.0.1", MXPref: "10", TTL: "1799"},
|
{Type: "A", Name: "home", Address: "10.0.0.1", MXPref: "10", TTL: "1799"},
|
||||||
{Type: "A", Name: "www", Address: "10.0.0.2", MXPref: "10", TTL: "1200"},
|
{Type: "A", Name: "www", Address: "10.0.0.2", MXPref: "10", TTL: "1200"},
|
||||||
{Type: "AAAA", Name: "a", Address: "::0", MXPref: "10", TTL: "1799"},
|
{Type: "AAAA", Name: "a", Address: "::0", MXPref: "10", TTL: "1799"},
|
||||||
|
@ -289,7 +292,7 @@ var testcases = []testcase{
|
||||||
{
|
{
|
||||||
name: "Test:Success:2",
|
name: "Test:Success:2",
|
||||||
domain: "example.com",
|
domain: "example.com",
|
||||||
hosts: []host{
|
hosts: []record{
|
||||||
{Type: "A", Name: "@", Address: "10.0.0.2", MXPref: "10", TTL: "1200"},
|
{Type: "A", Name: "@", Address: "10.0.0.2", MXPref: "10", TTL: "1200"},
|
||||||
{Type: "A", Name: "www", Address: "10.0.0.3", MXPref: "10", TTL: "60"},
|
{Type: "A", Name: "www", Address: "10.0.0.3", MXPref: "10", TTL: "60"},
|
||||||
},
|
},
|
||||||
|
|
|
@ -97,7 +97,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
return &DNSProvider{client: client, config: config}, nil
|
return &DNSProvider{client: client, config: config}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
// Present creates a TXT record to fulfill the dns-01 challenge.
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -38,10 +38,10 @@ func TestLiveNamedotcomPresent(t *testing.T) {
|
||||||
config.Server = namedotcomServer
|
config.Server = namedotcomServer
|
||||||
|
|
||||||
provider, err := NewDNSProviderConfig(config)
|
provider, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.Present(namedotcomDomain, "", "123d==")
|
err = provider.Present(namedotcomDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -61,8 +61,8 @@ func TestLiveNamedotcomCleanUp(t *testing.T) {
|
||||||
config.Server = namedotcomServer
|
config.Server = namedotcomServer
|
||||||
|
|
||||||
provider, err := NewDNSProviderConfig(config)
|
provider, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.CleanUp(namedotcomDomain, "", "123d==")
|
err = provider.CleanUp(namedotcomDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -31,10 +31,10 @@ func TestLivenifcloudPresent(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.Present(nifcloudDomain, "", "123d==")
|
err = provider.Present(nifcloudDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLivenifcloudCleanUp(t *testing.T) {
|
func TestLivenifcloudCleanUp(t *testing.T) {
|
||||||
|
@ -45,8 +45,8 @@ func TestLivenifcloudCleanUp(t *testing.T) {
|
||||||
time.Sleep(time.Second * 1)
|
time.Sleep(time.Second * 1)
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.CleanUp(nifcloudDomain, "", "123d==")
|
err = provider.CleanUp(nifcloudDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
return &DNSProvider{client: client, config: config}, nil
|
return &DNSProvider{client: client, config: config}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
// Present creates a TXT record to fulfill the dns-01 challenge.
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ func TestNewDNSProviderValid(t *testing.T) {
|
||||||
config.APIKey = "123"
|
config.APIKey = "123"
|
||||||
|
|
||||||
_, err := NewDNSProviderConfig(config)
|
_, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||||
|
@ -106,10 +106,10 @@ func TestLivePresent(t *testing.T) {
|
||||||
config.APIKey = apiKey
|
config.APIKey = apiKey
|
||||||
|
|
||||||
provider, err := NewDNSProviderConfig(config)
|
provider, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.Present(domain, "", "123d==")
|
err = provider.Present(domain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLiveCleanUp(t *testing.T) {
|
func TestLiveCleanUp(t *testing.T) {
|
||||||
|
@ -123,8 +123,8 @@ func TestLiveCleanUp(t *testing.T) {
|
||||||
config.APIKey = apiKey
|
config.APIKey = apiKey
|
||||||
|
|
||||||
provider, err := NewDNSProviderConfig(config)
|
provider, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.CleanUp(domain, "", "123d==")
|
err = provider.CleanUp(domain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
// Present creates a TXT record to fulfill the dns-01 challenge.
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -40,7 +41,7 @@ func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
os.Setenv("OVH_CONSUMER_KEY", "abcde")
|
os.Setenv("OVH_CONSUMER_KEY", "abcde")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||||
|
@ -123,10 +124,10 @@ func TestLivePresent(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.Present(domain, "", "123d==")
|
err = provider.Present(domain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLiveCleanUp(t *testing.T) {
|
func TestLiveCleanUp(t *testing.T) {
|
||||||
|
@ -137,8 +138,8 @@ func TestLiveCleanUp(t *testing.T) {
|
||||||
time.Sleep(time.Second * 1)
|
time.Sleep(time.Second * 1)
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.CleanUp(domain, "", "123d==")
|
err = provider.CleanUp(domain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge
|
// Present creates a TXT record to fulfill the dns-01 challenge
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
zone, err := d.getHostedZone(fqdn)
|
zone, err := d.getHostedZone(fqdn)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -43,7 +44,7 @@ func TestNewDNSProviderValid(t *testing.T) {
|
||||||
config.APIKey = "123"
|
config.APIKey = "123"
|
||||||
|
|
||||||
_, err := NewDNSProviderConfig(config)
|
_, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderValidEnv(t *testing.T) {
|
func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
|
@ -52,7 +53,7 @@ func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
os.Setenv("PDNS_API_KEY", "123")
|
os.Setenv("PDNS_API_KEY", "123")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingHostErr(t *testing.T) {
|
func TestNewDNSProviderMissingHostErr(t *testing.T) {
|
||||||
|
@ -83,11 +84,11 @@ func TestPdnsPresentAndCleanup(t *testing.T) {
|
||||||
config.APIKey = pdnsAPIKey
|
config.APIKey = pdnsAPIKey
|
||||||
|
|
||||||
provider, err := NewDNSProviderConfig(config)
|
provider, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.Present(pdnsDomain, "", "123d==")
|
err = provider.Present(pdnsDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.CleanUp(pdnsDomain, "", "123d==")
|
err = provider.CleanUp(pdnsDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,7 +146,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge
|
// Present creates a TXT record to fulfill the dns-01 challenge
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
zoneID, err := d.getHostedZoneID(fqdn)
|
zoneID, err := d.getHostedZoneID(fqdn)
|
||||||
|
|
|
@ -180,7 +180,7 @@ func TestOfflineRackspaceCleanUp(t *testing.T) {
|
||||||
|
|
||||||
if assert.NoError(t, err) {
|
if assert.NoError(t, err) {
|
||||||
err = provider.CleanUp("example.com", "token", "keyAuth")
|
err = provider.CleanUp("example.com", "token", "keyAuth")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
|
|
||||||
liveRackspaceEnv()
|
liveRackspaceEnv()
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Contains(t, provider.cloudDNSEndpoint, "https://dns.api.rackspacecloud.com/v1.0/", "The endpoint URL should contain the base")
|
assert.Contains(t, provider.cloudDNSEndpoint, "https://dns.api.rackspacecloud.com/v1.0/", "The endpoint URL should contain the base")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,10 +202,10 @@ func TestRackspacePresent(t *testing.T) {
|
||||||
|
|
||||||
liveRackspaceEnv()
|
liveRackspaceEnv()
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.Present(rackspaceDomain, "", "112233445566==")
|
err = provider.Present(rackspaceDomain, "", "112233445566==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRackspaceCleanUp(t *testing.T) {
|
func TestRackspaceCleanUp(t *testing.T) {
|
||||||
|
@ -217,10 +217,10 @@ func TestRackspaceCleanUp(t *testing.T) {
|
||||||
|
|
||||||
liveRackspaceEnv()
|
liveRackspaceEnv()
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.CleanUp(rackspaceDomain, "", "112233445566==")
|
err = provider.CleanUp(rackspaceDomain, "", "112233445566==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -33,9 +33,14 @@ func TestRFC2136CanaryLocalTestServer(t *testing.T) {
|
||||||
dns.HandleFunc("example.com.", serverHandlerHello)
|
dns.HandleFunc("example.com.", serverHandlerHello)
|
||||||
defer dns.HandleRemove("example.com.")
|
defer dns.HandleRemove("example.com.")
|
||||||
|
|
||||||
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
|
server, addrstr, err := runLocalDNSTestServer(false)
|
||||||
require.NoError(t, err, "Failed to start test server")
|
require.NoError(t, err, "Failed to start test server")
|
||||||
defer server.Shutdown()
|
defer func() {
|
||||||
|
errS := server.Shutdown()
|
||||||
|
if errS != nil {
|
||||||
|
t.Log(errS)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
c := new(dns.Client)
|
c := new(dns.Client)
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
|
@ -55,9 +60,14 @@ func TestRFC2136ServerSuccess(t *testing.T) {
|
||||||
dns.HandleFunc(rfc2136TestZone, serverHandlerReturnSuccess)
|
dns.HandleFunc(rfc2136TestZone, serverHandlerReturnSuccess)
|
||||||
defer dns.HandleRemove(rfc2136TestZone)
|
defer dns.HandleRemove(rfc2136TestZone)
|
||||||
|
|
||||||
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
|
server, addrstr, err := runLocalDNSTestServer(false)
|
||||||
require.NoError(t, err, "Failed to start test server")
|
require.NoError(t, err, "Failed to start test server")
|
||||||
defer server.Shutdown()
|
defer func() {
|
||||||
|
errS := server.Shutdown()
|
||||||
|
if errS != nil {
|
||||||
|
t.Log(errS)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
config := NewDefaultConfig()
|
config := NewDefaultConfig()
|
||||||
config.Nameserver = addrstr
|
config.Nameserver = addrstr
|
||||||
|
@ -74,9 +84,14 @@ func TestRFC2136ServerError(t *testing.T) {
|
||||||
dns.HandleFunc(rfc2136TestZone, serverHandlerReturnErr)
|
dns.HandleFunc(rfc2136TestZone, serverHandlerReturnErr)
|
||||||
defer dns.HandleRemove(rfc2136TestZone)
|
defer dns.HandleRemove(rfc2136TestZone)
|
||||||
|
|
||||||
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
|
server, addrstr, err := runLocalDNSTestServer(false)
|
||||||
require.NoError(t, err, "Failed to start test server")
|
require.NoError(t, err, "Failed to start test server")
|
||||||
defer server.Shutdown()
|
defer func() {
|
||||||
|
errS := server.Shutdown()
|
||||||
|
if errS != nil {
|
||||||
|
t.Log(errS)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
config := NewDefaultConfig()
|
config := NewDefaultConfig()
|
||||||
config.Nameserver = addrstr
|
config.Nameserver = addrstr
|
||||||
|
@ -96,9 +111,14 @@ func TestRFC2136TsigClient(t *testing.T) {
|
||||||
dns.HandleFunc(rfc2136TestZone, serverHandlerReturnSuccess)
|
dns.HandleFunc(rfc2136TestZone, serverHandlerReturnSuccess)
|
||||||
defer dns.HandleRemove(rfc2136TestZone)
|
defer dns.HandleRemove(rfc2136TestZone)
|
||||||
|
|
||||||
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", true)
|
server, addrstr, err := runLocalDNSTestServer(true)
|
||||||
require.NoError(t, err, "Failed to start test server")
|
require.NoError(t, err, "Failed to start test server")
|
||||||
defer server.Shutdown()
|
defer func() {
|
||||||
|
errS := server.Shutdown()
|
||||||
|
if errS != nil {
|
||||||
|
t.Log(errS)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
config := NewDefaultConfig()
|
config := NewDefaultConfig()
|
||||||
config.Nameserver = addrstr
|
config.Nameserver = addrstr
|
||||||
|
@ -117,9 +137,14 @@ func TestRFC2136ValidUpdatePacket(t *testing.T) {
|
||||||
dns.HandleFunc(rfc2136TestZone, serverHandlerPassBackRequest)
|
dns.HandleFunc(rfc2136TestZone, serverHandlerPassBackRequest)
|
||||||
defer dns.HandleRemove(rfc2136TestZone)
|
defer dns.HandleRemove(rfc2136TestZone)
|
||||||
|
|
||||||
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
|
server, addrstr, err := runLocalDNSTestServer(false)
|
||||||
require.NoError(t, err, "Failed to start test server")
|
require.NoError(t, err, "Failed to start test server")
|
||||||
defer server.Shutdown()
|
defer func() {
|
||||||
|
errS := server.Shutdown()
|
||||||
|
if errS != nil {
|
||||||
|
t.Log(errS)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
txtRR, _ := dns.NewRR(fmt.Sprintf("%s %d IN TXT %s", rfc2136TestFqdn, rfc2136TestTTL, rfc2136TestValue))
|
txtRR, _ := dns.NewRR(fmt.Sprintf("%s %d IN TXT %s", rfc2136TestFqdn, rfc2136TestTTL, rfc2136TestValue))
|
||||||
rrs := []dns.RR{txtRR}
|
rrs := []dns.RR{txtRR}
|
||||||
|
@ -157,8 +182,8 @@ func TestRFC2136ValidUpdatePacket(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runLocalDNSTestServer(listenAddr string, tsig bool) (*dns.Server, string, error) {
|
func runLocalDNSTestServer(tsig bool) (*dns.Server, string, error) {
|
||||||
pc, err := net.ListenPacket("udp", listenAddr)
|
pc, err := net.ListenPacket("udp", "127.0.0.1:0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
@ -172,7 +197,7 @@ func runLocalDNSTestServer(listenAddr string, tsig bool) (*dns.Server, string, e
|
||||||
server.NotifyStartedFunc = waitLock.Unlock
|
server.NotifyStartedFunc = waitLock.Unlock
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
server.ActivateAndServe()
|
_ = server.ActivateAndServe()
|
||||||
pc.Close()
|
pc.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -188,7 +213,7 @@ func serverHandlerHello(w dns.ResponseWriter, req *dns.Msg) {
|
||||||
Hdr: dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0},
|
Hdr: dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0},
|
||||||
Txt: []string{"Hello world"},
|
Txt: []string{"Hello world"},
|
||||||
}
|
}
|
||||||
w.WriteMsg(m)
|
_ = w.WriteMsg(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func serverHandlerReturnSuccess(w dns.ResponseWriter, req *dns.Msg) {
|
func serverHandlerReturnSuccess(w dns.ResponseWriter, req *dns.Msg) {
|
||||||
|
@ -207,13 +232,13 @@ func serverHandlerReturnSuccess(w dns.ResponseWriter, req *dns.Msg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteMsg(m)
|
_ = w.WriteMsg(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func serverHandlerReturnErr(w dns.ResponseWriter, req *dns.Msg) {
|
func serverHandlerReturnErr(w dns.ResponseWriter, req *dns.Msg) {
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
m.SetRcode(req, dns.RcodeNotZone)
|
m.SetRcode(req, dns.RcodeNotZone)
|
||||||
w.WriteMsg(m)
|
_ = w.WriteMsg(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func serverHandlerPassBackRequest(w dns.ResponseWriter, req *dns.Msg) {
|
func serverHandlerPassBackRequest(w dns.ResponseWriter, req *dns.Msg) {
|
||||||
|
@ -232,7 +257,7 @@ func serverHandlerPassBackRequest(w dns.ResponseWriter, req *dns.Msg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteMsg(m)
|
_ = w.WriteMsg(m)
|
||||||
if req.Opcode != dns.OpcodeQuery || req.Question[0].Qtype != dns.TypeSOA || req.Question[0].Qclass != dns.ClassINET {
|
if req.Opcode != dns.OpcodeQuery || req.Question[0].Qtype != dns.TypeSOA || req.Question[0].Qclass != dns.ClassINET {
|
||||||
// Only talk back when it is not the SOA RR.
|
// Only talk back when it is not the SOA RR.
|
||||||
reqChan <- req
|
reqChan <- req
|
||||||
|
|
|
@ -19,35 +19,36 @@ func TestRoute53TTL(t *testing.T) {
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.Present(config["R53_DOMAIN"], "foo", "bar")
|
r53Domain := config["R53_DOMAIN"]
|
||||||
|
|
||||||
|
err = provider.Present(r53Domain, "foo", "bar")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// we need a separate R53 client here as the one in the DNS provider is
|
// we need a separate R53 client here as the one in the DNS provider is unexported.
|
||||||
// unexported.
|
fqdn := "_acme-challenge." + r53Domain + "."
|
||||||
fqdn := "_acme-challenge." + config["R53_DOMAIN"] + "."
|
|
||||||
svc := route53.New(session.New())
|
svc := route53.New(session.New())
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
errC := provider.CleanUp(r53Domain, "foo", "bar")
|
||||||
|
if errC != nil {
|
||||||
|
t.Log(errC)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
zoneID, err := provider.getHostedZoneID(fqdn)
|
zoneID, err := provider.getHostedZoneID(fqdn)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
provider.CleanUp(config["R53_DOMAIN"], "foo", "bar")
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
params := &route53.ListResourceRecordSetsInput{
|
params := &route53.ListResourceRecordSetsInput{
|
||||||
HostedZoneId: aws.String(zoneID),
|
HostedZoneId: aws.String(zoneID),
|
||||||
}
|
}
|
||||||
resp, err := svc.ListResourceRecordSets(params)
|
resp, err := svc.ListResourceRecordSets(params)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
provider.CleanUp(config["R53_DOMAIN"], "foo", "bar")
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range resp.ResourceRecordSets {
|
for _, v := range resp.ResourceRecordSets {
|
||||||
if aws.StringValue(v.Name) == fqdn && aws.StringValue(v.Type) == "TXT" && aws.Int64Value(v.TTL) == 10 {
|
if aws.StringValue(v.Name) == fqdn && aws.StringValue(v.Type) == "TXT" && aws.Int64Value(v.TTL) == 10 {
|
||||||
provider.CleanUp(config["R53_DOMAIN"], "foo", "bar")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
provider.CleanUp(config["R53_DOMAIN"], "foo", "bar")
|
t.Fatalf("Could not find a TXT record for _acme-challenge.%s with a TTL of 10", r53Domain)
|
||||||
t.Fatalf("Could not find a TXT record for _acme-challenge.%s with a TTL of 10", config["R53_DOMAIN"])
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,11 @@ func newMockServer(t *testing.T, responses MockResponseMap) *httptest.Server {
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/xml")
|
w.Header().Set("Content-Type", "application/xml")
|
||||||
w.WriteHeader(resp.StatusCode)
|
w.WriteHeader(resp.StatusCode)
|
||||||
w.Write([]byte(resp.Body))
|
_, err := w.Write([]byte(resp.Body))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
|
@ -85,7 +85,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
return &DNSProvider{client: client}, nil
|
return &DNSProvider{client: client}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
// Present creates a TXT record to fulfill the dns-01 challenge.
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ func TestNewDNSProviderValid(t *testing.T) {
|
||||||
|
|
||||||
assert.NotNil(t, provider)
|
assert.NotNil(t, provider)
|
||||||
assert.Equal(t, acme.UserAgent, provider.client.UserAgent)
|
assert.Equal(t, acme.UserAgent, provider.client.UserAgent)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderInvalidWithMissingAccessToken(t *testing.T) {
|
func TestNewDNSProviderInvalidWithMissingAccessToken(t *testing.T) {
|
||||||
|
@ -96,10 +96,10 @@ func TestLiveSakuraCloudPresent(t *testing.T) {
|
||||||
config.Secret = sakuracloudAccessSecret
|
config.Secret = sakuracloudAccessSecret
|
||||||
|
|
||||||
provider, err := NewDNSProviderConfig(config)
|
provider, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.Present(sakuracloudDomain, "", "123d==")
|
err = provider.Present(sakuracloudDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -118,8 +118,8 @@ func TestLiveSakuraCloudCleanUp(t *testing.T) {
|
||||||
config.Secret = sakuracloudAccessSecret
|
config.Secret = sakuracloudAccessSecret
|
||||||
|
|
||||||
provider, err := NewDNSProviderConfig(config)
|
provider, err := NewDNSProviderConfig(config)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.CleanUp(sakuracloudDomain, "", "123d==")
|
err = provider.CleanUp(sakuracloudDomain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the dns-01 challenge
|
// Present creates a TXT record to fulfill the dns-01 challenge
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const testDomain = "example.com"
|
||||||
|
|
||||||
var ipPort = "127.0.0.1:2112"
|
var ipPort = "127.0.0.1:2112"
|
||||||
|
|
||||||
var jsonMap = map[string]string{
|
var jsonMap = map[string]string{
|
||||||
|
@ -122,88 +124,90 @@ func TestVegaDNSTimeoutSuccess(t *testing.T) {
|
||||||
assert.Equal(t, interval, time.Duration(60000000000))
|
assert.Equal(t, interval, time.Duration(60000000000))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVegaDNSPresentSuccess(t *testing.T) {
|
func TestDNSProvider_Present(t *testing.T) {
|
||||||
ts, err := startTestServer(vegaDNSMuxSuccess)
|
testCases := []struct {
|
||||||
require.NoError(t, err)
|
desc string
|
||||||
|
callback muxCallback
|
||||||
|
expectedError string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "Success",
|
||||||
|
callback: vegaDNSMuxSuccess,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "FailToFindZone",
|
||||||
|
callback: vegaDNSMuxFailToFindZone,
|
||||||
|
expectedError: "vegadns: can't find Authoritative Zone for _acme-challenge.example.com. in Present: Unable to find auth zone for fqdn _acme-challenge.example.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "FailToCreateTXT",
|
||||||
|
callback: vegaDNSMuxFailToCreateTXT,
|
||||||
|
expectedError: "vegadns: Got bad answer from VegaDNS on CreateTXT. Code: 400. Message: ",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
defer ts.Close()
|
for _, test := range testCases {
|
||||||
defer os.Clearenv()
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
ts, err := startTestServer(test.callback)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
defer ts.Close()
|
||||||
require.NoError(t, err)
|
defer os.Clearenv()
|
||||||
|
|
||||||
err = provider.Present("example.com", "token", "keyAuth")
|
provider, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = provider.Present(testDomain, "token", "keyAuth")
|
||||||
|
if len(test.expectedError) == 0 {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
} else {
|
||||||
|
assert.EqualError(t, err, test.expectedError)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVegaDNSPresentFailToFindZone(t *testing.T) {
|
func TestDNSProvider_CleanUp(t *testing.T) {
|
||||||
ts, err := startTestServer(vegaDNSMuxFailToFindZone)
|
testCases := []struct {
|
||||||
require.NoError(t, err)
|
desc string
|
||||||
|
callback muxCallback
|
||||||
|
expectedError string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "Success",
|
||||||
|
callback: vegaDNSMuxSuccess,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "FailToFindZone",
|
||||||
|
callback: vegaDNSMuxFailToFindZone,
|
||||||
|
expectedError: "vegadns: can't find Authoritative Zone for _acme-challenge.example.com. in CleanUp: Unable to find auth zone for fqdn _acme-challenge.example.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "FailToGetRecordID",
|
||||||
|
callback: vegaDNSMuxFailToGetRecordID,
|
||||||
|
expectedError: "vegadns: couldn't get Record ID in CleanUp: Got bad answer from VegaDNS on GetRecordID. Code: 404. Message: ",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
defer ts.Close()
|
for _, test := range testCases {
|
||||||
defer os.Clearenv()
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
ts, err := startTestServer(test.callback)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
defer ts.Close()
|
||||||
require.NoError(t, err)
|
defer os.Clearenv()
|
||||||
|
|
||||||
err = provider.Present("example.com", "token", "keyAuth")
|
provider, err := NewDNSProvider()
|
||||||
assert.EqualError(t, err, "vegadns: can't find Authoritative Zone for _acme-challenge.example.com. in Present: Unable to find auth zone for fqdn _acme-challenge.example.com")
|
require.NoError(t, err)
|
||||||
}
|
|
||||||
|
|
||||||
func TestVegaDNSPresentFailToCreateTXT(t *testing.T) {
|
err = provider.CleanUp(testDomain, "token", "keyAuth")
|
||||||
ts, err := startTestServer(vegaDNSMuxFailToCreateTXT)
|
if len(test.expectedError) == 0 {
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
} else {
|
||||||
defer ts.Close()
|
assert.EqualError(t, err, test.expectedError)
|
||||||
defer os.Clearenv()
|
}
|
||||||
|
})
|
||||||
provider, err := NewDNSProvider()
|
}
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
err = provider.Present("example.com", "token", "keyAuth")
|
|
||||||
assert.EqualError(t, err, "vegadns: Got bad answer from VegaDNS on CreateTXT. Code: 400. Message: ")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestVegaDNSCleanUpSuccess(t *testing.T) {
|
|
||||||
ts, err := startTestServer(vegaDNSMuxSuccess)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
defer ts.Close()
|
|
||||||
defer os.Clearenv()
|
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
err = provider.CleanUp("example.com", "token", "keyAuth")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestVegaDNSCleanUpFailToFindZone(t *testing.T) {
|
|
||||||
ts, err := startTestServer(vegaDNSMuxFailToFindZone)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
defer ts.Close()
|
|
||||||
defer os.Clearenv()
|
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
err = provider.CleanUp("example.com", "token", "keyAuth")
|
|
||||||
assert.EqualError(t, err, "vegadns: can't find Authoritative Zone for _acme-challenge.example.com. in CleanUp: Unable to find auth zone for fqdn _acme-challenge.example.com")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestVegaDNSCleanUpFailToGetRecordID(t *testing.T) {
|
|
||||||
ts, err := startTestServer(vegaDNSMuxFailToGetRecordID)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
defer ts.Close()
|
|
||||||
defer os.Clearenv()
|
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
err = provider.CleanUp("example.com", "token", "keyAuth")
|
|
||||||
assert.EqualError(t, err, "vegadns: couldn't get Record ID in CleanUp: Got bad answer from VegaDNS on GetRecordID. Code: 404. Message: ")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func vegaDNSMuxSuccess() *http.ServeMux {
|
func vegaDNSMuxSuccess() *http.ServeMux {
|
||||||
|
@ -298,7 +302,7 @@ func vegaDNSMuxFailToCreateTXT() *http.ServeMux {
|
||||||
})
|
})
|
||||||
|
|
||||||
mux.HandleFunc("/1.0/domains", func(w http.ResponseWriter, r *http.Request) {
|
mux.HandleFunc("/1.0/domains", func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.URL.Query().Get("search") == "example.com" {
|
if r.URL.Query().Get("search") == testDomain {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
fmt.Fprintf(w, jsonMap["domains"])
|
fmt.Fprintf(w, jsonMap["domains"])
|
||||||
return
|
return
|
||||||
|
@ -340,7 +344,7 @@ func vegaDNSMuxFailToGetRecordID() *http.ServeMux {
|
||||||
})
|
})
|
||||||
|
|
||||||
mux.HandleFunc("/1.0/domains", func(w http.ResponseWriter, r *http.Request) {
|
mux.HandleFunc("/1.0/domains", func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.URL.Query().Get("search") == "example.com" {
|
if r.URL.Query().Get("search") == testDomain {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
fmt.Fprintf(w, jsonMap["domains"])
|
fmt.Fprintf(w, jsonMap["domains"])
|
||||||
return
|
return
|
||||||
|
|
|
@ -90,7 +90,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
return &DNSProvider{client: client, config: config}, nil
|
return &DNSProvider{client: client, config: config}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfil the DNS-01 challenge.
|
// Present creates a TXT record to fulfill the DNS-01 challenge.
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -29,7 +30,7 @@ func TestNewDNSProviderValidEnv(t *testing.T) {
|
||||||
os.Setenv("VULTR_API_KEY", "123")
|
os.Setenv("VULTR_API_KEY", "123")
|
||||||
|
|
||||||
_, err := NewDNSProvider()
|
_, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
func TestNewDNSProviderMissingCredErr(t *testing.T) {
|
||||||
|
@ -46,10 +47,10 @@ func TestLivePresent(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.Present(domain, "", "123d==")
|
err = provider.Present(domain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLiveCleanUp(t *testing.T) {
|
func TestLiveCleanUp(t *testing.T) {
|
||||||
|
@ -60,8 +61,8 @@ func TestLiveCleanUp(t *testing.T) {
|
||||||
time.Sleep(time.Second * 1)
|
time.Sleep(time.Second * 1)
|
||||||
|
|
||||||
provider, err := NewDNSProvider()
|
provider, err := NewDNSProvider()
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.CleanUp(domain, "", "123d==")
|
err = provider.CleanUp(domain, "", "123d==")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/rainycape/memcache"
|
"github.com/rainycape/memcache"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ func TestNewMemcachedProviderValid(t *testing.T) {
|
||||||
t.Skip("Skipping memcached tests")
|
t.Skip("Skipping memcached tests")
|
||||||
}
|
}
|
||||||
_, err := NewMemcachedProvider(memcachedHosts)
|
_, err := NewMemcachedProvider(memcachedHosts)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMemcachedPresentSingleHost(t *testing.T) {
|
func TestMemcachedPresentSingleHost(t *testing.T) {
|
||||||
|
@ -47,16 +48,16 @@ func TestMemcachedPresentSingleHost(t *testing.T) {
|
||||||
t.Skip("Skipping memcached tests")
|
t.Skip("Skipping memcached tests")
|
||||||
}
|
}
|
||||||
p, err := NewMemcachedProvider(memcachedHosts[0:1])
|
p, err := NewMemcachedProvider(memcachedHosts[0:1])
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
challengePath := path.Join("/", acme.HTTP01ChallengePath(token))
|
challengePath := path.Join("/", acme.HTTP01ChallengePath(token))
|
||||||
|
|
||||||
err = p.Present(domain, token, keyAuth)
|
err = p.Present(domain, token, keyAuth)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
mc, err := memcache.New(memcachedHosts[0])
|
mc, err := memcache.New(memcachedHosts[0])
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
i, err := mc.Get(challengePath)
|
i, err := mc.Get(challengePath)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, i.Value, []byte(keyAuth))
|
assert.Equal(t, i.Value, []byte(keyAuth))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,17 +66,17 @@ func TestMemcachedPresentMultiHost(t *testing.T) {
|
||||||
t.Skip("Skipping memcached multi-host tests")
|
t.Skip("Skipping memcached multi-host tests")
|
||||||
}
|
}
|
||||||
p, err := NewMemcachedProvider(memcachedHosts)
|
p, err := NewMemcachedProvider(memcachedHosts)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
challengePath := path.Join("/", acme.HTTP01ChallengePath(token))
|
challengePath := path.Join("/", acme.HTTP01ChallengePath(token))
|
||||||
|
|
||||||
err = p.Present(domain, token, keyAuth)
|
err = p.Present(domain, token, keyAuth)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
for _, host := range memcachedHosts {
|
for _, host := range memcachedHosts {
|
||||||
mc, err := memcache.New(host)
|
mc, err := memcache.New(host)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
i, err := mc.Get(challengePath)
|
i, err := mc.Get(challengePath)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, i.Value, []byte(keyAuth))
|
assert.Equal(t, i.Value, []byte(keyAuth))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,17 +87,17 @@ func TestMemcachedPresentPartialFailureMultiHost(t *testing.T) {
|
||||||
}
|
}
|
||||||
hosts := append(memcachedHosts, "5.5.5.5:11211")
|
hosts := append(memcachedHosts, "5.5.5.5:11211")
|
||||||
p, err := NewMemcachedProvider(hosts)
|
p, err := NewMemcachedProvider(hosts)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
challengePath := path.Join("/", acme.HTTP01ChallengePath(token))
|
challengePath := path.Join("/", acme.HTTP01ChallengePath(token))
|
||||||
|
|
||||||
err = p.Present(domain, token, keyAuth)
|
err = p.Present(domain, token, keyAuth)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
for _, host := range memcachedHosts {
|
for _, host := range memcachedHosts {
|
||||||
mc, err := memcache.New(host)
|
mc, err := memcache.New(host)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
i, err := mc.Get(challengePath)
|
i, err := mc.Get(challengePath)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, i.Value, []byte(keyAuth))
|
assert.Equal(t, i.Value, []byte(keyAuth))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,6 +107,6 @@ func TestMemcachedCleanup(t *testing.T) {
|
||||||
t.Skip("Skipping memcached tests")
|
t.Skip("Skipping memcached tests")
|
||||||
}
|
}
|
||||||
p, err := NewMemcachedProvider(memcachedHosts)
|
p, err := NewMemcachedProvider(memcachedHosts)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NoError(t, p.CleanUp(domain, token, keyAuth))
|
require.NoError(t, p.CleanUp(domain, token, keyAuth))
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,14 +18,10 @@ type HTTPProvider struct {
|
||||||
// NewHTTPProvider returns a HTTPProvider instance with a configured webroot path
|
// NewHTTPProvider returns a HTTPProvider instance with a configured webroot path
|
||||||
func NewHTTPProvider(path string) (*HTTPProvider, error) {
|
func NewHTTPProvider(path string) (*HTTPProvider, error) {
|
||||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
return nil, fmt.Errorf("Webroot path does not exist")
|
return nil, fmt.Errorf("webroot path does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
c := &HTTPProvider{
|
return &HTTPProvider{path: path}, nil
|
||||||
path: path,
|
|
||||||
}
|
|
||||||
|
|
||||||
return c, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present makes the token available at `HTTP01ChallengePath(token)` by creating a file in the given webroot path
|
// Present makes the token available at `HTTP01ChallengePath(token)` by creating a file in the given webroot path
|
||||||
|
|
|
@ -4,6 +4,9 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHTTPProvider(t *testing.T) {
|
func TestHTTPProvider(t *testing.T) {
|
||||||
|
@ -13,34 +16,26 @@ func TestHTTPProvider(t *testing.T) {
|
||||||
keyAuth := "keyAuth"
|
keyAuth := "keyAuth"
|
||||||
challengeFilePath := webroot + "/.well-known/acme-challenge/" + token
|
challengeFilePath := webroot + "/.well-known/acme-challenge/" + token
|
||||||
|
|
||||||
os.MkdirAll(webroot+"/.well-known/acme-challenge", 0777)
|
require.NoError(t, os.MkdirAll(webroot+"/.well-known/acme-challenge", 0777))
|
||||||
defer os.RemoveAll(webroot)
|
defer os.RemoveAll(webroot)
|
||||||
|
|
||||||
provider, err := NewHTTPProvider(webroot)
|
provider, err := NewHTTPProvider(webroot)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Errorf("Webroot provider error: got %v, want nil", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = provider.Present(domain, token, keyAuth)
|
err = provider.Present(domain, token, keyAuth)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Errorf("Webroot provider present() error: got %v, want nil", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := os.Stat(challengeFilePath); os.IsNotExist(err) {
|
if _, err = os.Stat(challengeFilePath); os.IsNotExist(err) {
|
||||||
t.Error("Challenge file was not created in webroot")
|
t.Error("Challenge file was not created in webroot")
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadFile(challengeFilePath)
|
var data []byte
|
||||||
if err != nil {
|
data, err = ioutil.ReadFile(challengeFilePath)
|
||||||
t.Errorf("Webroot provider ReadFile() error: got %v, want nil", err)
|
require.NoError(t, err)
|
||||||
}
|
|
||||||
dataStr := string(data)
|
dataStr := string(data)
|
||||||
if dataStr != keyAuth {
|
assert.Equal(t, keyAuth, dataStr)
|
||||||
t.Errorf("Challenge file content: got %q, want %q", dataStr, keyAuth)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = provider.CleanUp(domain, token, keyAuth)
|
err = provider.CleanUp(domain, token, keyAuth)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Errorf("Webroot provider CleanUp() error: got %v, want nil", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue