Skip to content

Commit 584d374

Browse files
authored
acme-dns: use new registred account (#2445)
1 parent d183572 commit 584d374

File tree

3 files changed

+232
-121
lines changed

3 files changed

+232
-121
lines changed

providers/dns/acmedns/acmedns.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ func (d *DNSProvider) Present(domain, _, keyAuth string) error {
178178

179179
// The account did not exist.
180180
// Create a new one and return an error indicating the required one-time manual CNAME setup.
181-
err = d.register(ctx, domain, info.FQDN)
181+
account, err = d.register(ctx, domain, info.FQDN)
182182
if err != nil {
183183
return err
184184
}
@@ -200,10 +200,10 @@ func (d *DNSProvider) CleanUp(_, _, _ string) error {
200200
// If account creation works as expected a ErrCNAMERequired error is returned describing
201201
// the one-time manual CNAME setup required to complete setup of the ACME-DNS hook for the domain.
202202
// If any other error occurs it is returned as-is.
203-
func (d *DNSProvider) register(ctx context.Context, domain, fqdn string) error {
203+
func (d *DNSProvider) register(ctx context.Context, domain, fqdn string) (goacmedns.Account, error) {
204204
newAcct, err := d.client.RegisterAccount(ctx, d.config.AllowList)
205205
if err != nil {
206-
return err
206+
return goacmedns.Account{}, err
207207
}
208208

209209
var cnameCreated bool
@@ -213,23 +213,23 @@ func (d *DNSProvider) register(ctx context.Context, domain, fqdn string) error {
213213
if err != nil {
214214
cnameCreated = errors.Is(err, internal.ErrCNAMEAlreadyCreated)
215215
if !cnameCreated {
216-
return err
216+
return goacmedns.Account{}, err
217217
}
218218
}
219219

220220
err = d.storage.Save(ctx)
221221
if err != nil {
222-
return err
222+
return goacmedns.Account{}, err
223223
}
224224

225225
if cnameCreated {
226-
return nil
226+
return newAcct, nil
227227
}
228228

229229
// Stop issuance by returning an error.
230230
// The user needs to perform a manual one-time CNAME setup in their DNS zone
231231
// to complete the setup of the new account we created.
232-
return ErrCNAMERequired{
232+
return goacmedns.Account{}, ErrCNAMERequired{
233233
Domain: domain,
234234
FQDN: fqdn,
235235
Target: newAcct.FullDomain,

providers/dns/acmedns/acmedns_test.go

Lines changed: 129 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package acmedns
22

33
import (
44
"context"
5+
"net/http"
6+
"net/http/httptest"
57
"testing"
68

79
"github.com/nrdcg/goacmedns"
@@ -10,27 +12,17 @@ import (
1012
)
1113

1214
const (
13-
// Fixed test data for unit tests.
1415
egDomain = "example.com"
1516
egFQDN = "_acme-challenge." + egDomain + "."
1617
egKeyAuth = "⚷"
1718
)
1819

19-
// TestPresent tests that the ACME-DNS Present function for updating a DNS-01
20-
// challenge response TXT record works as expected.
2120
func TestPresent(t *testing.T) {
2221
// validAccountStorage is a mockStorage configured to return the egTestAccount.
23-
validAccountStorage := mockStorage{
24-
map[string]goacmedns.Account{
25-
egDomain: egTestAccount,
26-
},
27-
}
28-
// validUpdateClient is a mockClient configured with the egTestAccount that will
29-
// track TXT updates in a map.
30-
validUpdateClient := mockUpdateClient{
31-
mockClient{egTestAccount},
32-
make(map[goacmedns.Account]string),
33-
}
22+
validAccountStorage := newMockStorage().WithAccount(egDomain, egTestAccount)
23+
24+
// validUpdateClient is a mockClient configured with the egTestAccount that will track TXT updates in a map.
25+
validUpdateClient := newMockClient()
3426

3527
testCases := []struct {
3628
Name string
@@ -40,13 +32,13 @@ func TestPresent(t *testing.T) {
4032
}{
4133
{
4234
Name: "present when client storage returns unexpected error",
43-
Client: mockClient{egTestAccount},
44-
Storage: errorFetchStorage{},
35+
Client: newMockClient().WithRegisterAccount(egTestAccount),
36+
Storage: newMockStorage().WithFetchError(errorStorageErr),
4537
ExpectedError: errorStorageErr,
4638
},
4739
{
4840
Name: "present when client storage returns ErrDomainNotFound",
49-
Client: mockClient{egTestAccount},
41+
Client: newMockClient().WithRegisterAccount(egTestAccount),
5042
ExpectedError: ErrCNAMERequired{
5143
Domain: egDomain,
5244
FQDN: egFQDN,
@@ -55,7 +47,7 @@ func TestPresent(t *testing.T) {
5547
},
5648
{
5749
Name: "present when client UpdateTXTRecord returns unexpected error",
58-
Client: errorUpdateClient{},
50+
Client: newMockClient().WithUpdateTXTRecordError(errorClientErr),
5951
Storage: validAccountStorage,
6052
ExpectedError: errorClientErr,
6153
},
@@ -71,16 +63,13 @@ func TestPresent(t *testing.T) {
7163
p := &DNSProvider{
7264
config: NewDefaultConfig(),
7365
client: test.Client,
74-
storage: mockStorage{make(map[string]goacmedns.Account)},
66+
storage: newMockStorage(),
7567
}
7668

77-
// override the storage mock if required by the test case.
7869
if test.Storage != nil {
7970
p.storage = test.Storage
8071
}
8172

82-
// call Present. The token argument can be garbage because the ACME-DNS
83-
// provider does not use it.
8473
err := p.Present(egDomain, "foo", egKeyAuth)
8574
if test.ExpectedError != nil {
8675
assert.Equal(t, test.ExpectedError, err)
@@ -97,36 +86,33 @@ func TestPresent(t *testing.T) {
9786
assert.Len(t, validUpdateClient.records[egTestAccount], 43)
9887
}
9988

100-
// TestRegister tests that the ACME-DNS register function works correctly.
10189
func TestRegister(t *testing.T) {
10290
testCases := []struct {
10391
Name string
10492
Client acmeDNSClient
10593
Storage goacmedns.Storage
106-
Domain string
107-
FQDN string
10894
ExpectedError error
10995
}{
11096
{
11197
Name: "register when acme-dns client returns an error",
112-
Client: errorRegisterClient{},
98+
Client: newMockClient().WithRegisterAccountError(errorClientErr),
11399
ExpectedError: errorClientErr,
114100
},
115101
{
116102
Name: "register when acme-dns storage put returns an error",
117-
Client: mockClient{egTestAccount},
118-
Storage: errorPutStorage{mockStorage{make(map[string]goacmedns.Account)}},
103+
Client: newMockClient().WithRegisterAccount(egTestAccount),
104+
Storage: newMockStorage().WithPutError(errorStorageErr),
119105
ExpectedError: errorStorageErr,
120106
},
121107
{
122108
Name: "register when acme-dns storage save returns an error",
123-
Client: mockClient{egTestAccount},
124-
Storage: errorSaveStorage{mockStorage{make(map[string]goacmedns.Account)}},
109+
Client: newMockClient().WithRegisterAccount(egTestAccount),
110+
Storage: newMockStorage().WithSaveError(errorStorageErr),
125111
ExpectedError: errorStorageErr,
126112
},
127113
{
128114
Name: "register when everything works",
129-
Client: mockClient{egTestAccount},
115+
Client: newMockClient().WithRegisterAccount(egTestAccount),
130116
ExpectedError: ErrCNAMERequired{
131117
Domain: egDomain,
132118
FQDN: egFQDN,
@@ -140,20 +126,128 @@ func TestRegister(t *testing.T) {
140126
p := &DNSProvider{
141127
config: NewDefaultConfig(),
142128
client: test.Client,
143-
storage: mockStorage{make(map[string]goacmedns.Account)},
129+
storage: newMockStorage(),
144130
}
145131

146-
// override the storage mock if required by the testcase.
147132
if test.Storage != nil {
148133
p.storage = test.Storage
149134
}
150135

151-
// Call register for the example domain/fqdn.
152-
err := p.register(context.Background(), egDomain, egFQDN)
136+
acc, err := p.register(context.Background(), egDomain, egFQDN)
137+
if test.ExpectedError != nil {
138+
assert.Equal(t, test.ExpectedError, err)
139+
} else {
140+
assert.Equal(t, goacmedns.Account{}, acc)
141+
require.NoError(t, err)
142+
}
143+
})
144+
}
145+
}
146+
147+
func TestPresent_httpStorage(t *testing.T) {
148+
testCases := []struct {
149+
desc string
150+
StatusCode int
151+
ExpectedError error
152+
}{
153+
{
154+
desc: "the CNAME is not handled by the storage",
155+
StatusCode: http.StatusOK,
156+
ExpectedError: ErrCNAMERequired{
157+
Domain: egDomain,
158+
FQDN: egFQDN,
159+
Target: egTestAccount.FullDomain,
160+
},
161+
},
162+
{
163+
desc: "the CNAME is handled by the storage",
164+
StatusCode: http.StatusCreated,
165+
},
166+
}
167+
168+
for _, test := range testCases {
169+
t.Run(test.desc, func(t *testing.T) {
170+
mux := http.NewServeMux()
171+
server := httptest.NewServer(mux)
172+
173+
config := NewDefaultConfig()
174+
config.StorageBaseURL = server.URL
175+
176+
p, err := NewDNSProviderConfig(config)
177+
require.NoError(t, err)
178+
179+
client := newMockClient().WithRegisterAccount(egTestAccount)
180+
p.client = client
181+
182+
// Fetch
183+
mux.HandleFunc("GET /example.com", func(rw http.ResponseWriter, reg *http.Request) {
184+
rw.WriteHeader(http.StatusNotFound)
185+
})
186+
187+
// Put
188+
mux.HandleFunc("POST /example.com", func(rw http.ResponseWriter, req *http.Request) {
189+
rw.WriteHeader(test.StatusCode)
190+
})
191+
192+
err = p.Present(egDomain, "foo", egKeyAuth)
193+
if test.ExpectedError != nil {
194+
assert.Equal(t, test.ExpectedError, err)
195+
assert.True(t, client.registerAccountCalled)
196+
assert.False(t, client.updateTXTRecordCalled)
197+
} else {
198+
require.NoError(t, err)
199+
assert.True(t, client.registerAccountCalled)
200+
assert.True(t, client.updateTXTRecordCalled)
201+
}
202+
})
203+
}
204+
}
205+
206+
func TestRegister_httpStorage(t *testing.T) {
207+
testCases := []struct {
208+
Name string
209+
StatusCode int
210+
ExpectedError error
211+
}{
212+
{
213+
Name: "status code 200",
214+
StatusCode: http.StatusOK,
215+
ExpectedError: ErrCNAMERequired{
216+
Domain: egDomain,
217+
FQDN: egFQDN,
218+
Target: egTestAccount.FullDomain,
219+
},
220+
},
221+
{
222+
Name: "status code 201",
223+
StatusCode: http.StatusCreated,
224+
},
225+
}
226+
227+
for _, test := range testCases {
228+
t.Run(test.Name, func(t *testing.T) {
229+
mux := http.NewServeMux()
230+
server := httptest.NewServer(mux)
231+
232+
config := NewDefaultConfig()
233+
config.StorageBaseURL = server.URL
234+
235+
p, err := NewDNSProviderConfig(config)
236+
require.NoError(t, err)
237+
238+
p.client = newMockClient().WithRegisterAccount(egTestAccount)
239+
240+
// Put
241+
mux.HandleFunc("POST /example.com", func(w http.ResponseWriter, r *http.Request) {
242+
w.WriteHeader(test.StatusCode)
243+
})
244+
245+
acc, err := p.register(context.Background(), egDomain, egFQDN)
153246
if test.ExpectedError != nil {
154247
assert.Equal(t, test.ExpectedError, err)
155248
} else {
156249
require.NoError(t, err)
250+
assert.Equal(t, egTestAccount, acc)
157251
}
158252
})
159253
}

0 commit comments

Comments
 (0)