package gandi
import (
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"regexp"
"strings"
"testing"
"github.com/stretchr/testify/require"
"github.com/xenolf/lego/platform/tester"
)
var envTest = tester.NewEnvTest("GANDI_API_KEY")
func TestNewDNSProvider(t *testing.T) {
testCases := []struct {
desc string
envVars map[string]string
expected string
}{
{
desc: "success",
envVars: map[string]string{
"GANDI_API_KEY": "123",
},
},
{
desc: "missing api key",
envVars: map[string]string{
"GANDI_API_KEY": "",
},
expected: "gandi: some credentials information are missing: GANDI_API_KEY",
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
defer envTest.RestoreEnv()
envTest.ClearEnv()
envTest.Apply(test.envVars)
p, err := NewDNSProvider()
if len(test.expected) == 0 {
require.NoError(t, err)
require.NotNil(t, p)
require.NotNil(t, p.config)
require.NotNil(t, p.inProgressFQDNs)
require.NotNil(t, p.inProgressAuthZones)
} else {
require.EqualError(t, err, test.expected)
}
})
}
}
func TestNewDNSProviderConfig(t *testing.T) {
testCases := []struct {
desc string
apiKey string
expected string
}{
{
desc: "success",
apiKey: "123",
},
{
desc: "missing credentials",
expected: "gandi: no API Key given",
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
config := NewDefaultConfig()
config.APIKey = test.apiKey
p, err := NewDNSProviderConfig(config)
if len(test.expected) == 0 {
require.NoError(t, err)
require.NotNil(t, p)
require.NotNil(t, p.config)
require.NotNil(t, p.inProgressFQDNs)
require.NotNil(t, p.inProgressAuthZones)
} else {
require.EqualError(t, err, test.expected)
}
})
}
}
// TestDNSProvider runs Present and CleanUp against a fake Gandi RPC
// Server, whose responses are predetermined for particular requests.
func TestDNSProvider(t *testing.T) {
fakeKeyAuth := "XXXX"
regexpDate, err := regexp.Compile(`\[ACME Challenge [^\]:]*:[^\]]*\]`)
require.NoError(t, err)
// start fake RPC server
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")
req, errS := ioutil.ReadAll(r.Body)
require.NoError(t, errS)
req = regexpDate.ReplaceAllLiteral(req, []byte(`[ACME Challenge 01 Jan 16 00:00 +0000]`))
resp, ok := serverResponses[string(req)]
require.True(t, ok, "Server response for request not found")
_, errS = io.Copy(w, strings.NewReader(resp))
require.NoError(t, errS)
}))
defer fakeServer.Close()
// define function to override findZoneByFqdn with
fakeFindZoneByFqdn := func(fqdn string, nameserver []string) (string, error) {
return "example.com.", nil
}
config := NewDefaultConfig()
config.BaseURL = fakeServer.URL + "/"
config.APIKey = "123412341234123412341234"
provider, err := NewDNSProviderConfig(config)
require.NoError(t, err)
// override findZoneByFqdn function
savedFindZoneByFqdn := findZoneByFqdn
defer func() {
findZoneByFqdn = savedFindZoneByFqdn
}()
findZoneByFqdn = fakeFindZoneByFqdn
// run Present
err = provider.Present("abc.def.example.com", "", fakeKeyAuth)
require.NoError(t, err)
// run CleanUp
err = provider.CleanUp("abc.def.example.com", "", fakeKeyAuth)
require.NoError(t, err)
}
// serverResponses is the XML-RPC Request->Response map used by the
// fake RPC server. It was generated by recording a real RPC session
// which resulted in the successful issue of a cert, and then
// anonymizing the RPC data.
var serverResponses = map[string]string{
// Present Request->Response 1 (getZoneID)
`
domain.info
123412341234123412341234
example.com.
`: `
date_updated
20160216T16:14:23
date_delete
20170331T16:04:06
is_premium
0
date_hold_begin
20170215T02:04:06
date_registry_end
20170215T02:04:06
authinfo_expiration_date
20161211T21:31:20
contacts
owner
handle
LEGO-GANDI
id
111111
admin
handle
LEGO-GANDI
id
111111
bill
handle
LEGO-GANDI
id
111111
tech
handle
LEGO-GANDI
id
111111
reseller
nameservers
a.dns.gandi.net
b.dns.gandi.net
c.dns.gandi.net
date_restore_end
20170501T02:04:06
id
2222222
authinfo
ABCDABCDAB
status
clientTransferProhibited
serverTransferProhibited
tags
date_hold_end
20170401T02:04:06
services
gandidns
gandimail
date_pending_delete_end
20170506T02:04:06
zone_id
1234567
date_renew_begin
20120101T00:00:00
fqdn
example.com
autorenew
date_registry_creation
20150215T02:04:06
tld
org
date_created
20150215T03:04:06
`,
// Present Request->Response 2 (cloneZone)
`
domain.zone.clone
123412341234123412341234
1234567
0
name
example.com [ACME Challenge 01 Jan 16 00:00 +0000]
`: `
name
example.com [ACME Challenge 01 Jan 16 00:00 +0000]
versions
1
date_updated
20160216T16:24:29
id
7654321
owner
LEGO-GANDI
version
1
domains
0
public
0
`,
// Present Request->Response 3 (newZoneVersion)
`
domain.zone.version.new
123412341234123412341234
7654321
`: `
2
`,
// Present Request->Response 4 (addTXTRecord)
`
domain.zone.record.add
123412341234123412341234
7654321
2
type
TXT
name
_acme-challenge.abc.def
value
ezRpBPY8wH8djMLYjX2uCKPwiKDkFZ1SFMJ6ZXGlHrQ
ttl
300
`: `
name
_acme-challenge.abc.def
type
TXT
id
333333333
value
"ezRpBPY8wH8djMLYjX2uCKPwiKDkFZ1SFMJ6ZXGlHrQ"
ttl
300
`,
// Present Request->Response 5 (setZoneVersion)
`
domain.zone.version.set
123412341234123412341234
7654321
2
`: `
1
`,
// Present Request->Response 6 (setZone)
`
domain.zone.set
123412341234123412341234
example.com.
7654321
`: `
date_updated
20160216T16:14:23
date_delete
20170331T16:04:06
is_premium
0
date_hold_begin
20170215T02:04:06
date_registry_end
20170215T02:04:06
authinfo_expiration_date
20161211T21:31:20
contacts
owner
handle
LEGO-GANDI
id
111111
admin
handle
LEGO-GANDI
id
111111
bill
handle
LEGO-GANDI
id
111111
tech
handle
LEGO-GANDI
id
111111
reseller
nameservers
a.dns.gandi.net
b.dns.gandi.net
c.dns.gandi.net
date_restore_end
20170501T02:04:06
id
2222222
authinfo
ABCDABCDAB
status
clientTransferProhibited
serverTransferProhibited
tags
date_hold_end
20170401T02:04:06
services
gandidns
gandimail
date_pending_delete_end
20170506T02:04:06
zone_id
7654321
date_renew_begin
20120101T00:00:00
fqdn
example.com
autorenew
date_registry_creation
20150215T02:04:06
tld
org
date_created
20150215T03:04:06
`,
// CleanUp Request->Response 1 (setZone)
`
domain.zone.set
123412341234123412341234
example.com.
1234567
`: `
date_updated
20160216T16:24:38
date_delete
20170331T16:04:06
is_premium
0
date_hold_begin
20170215T02:04:06
date_registry_end
20170215T02:04:06
authinfo_expiration_date
20161211T21:31:20
contacts
owner
handle
LEGO-GANDI
id
111111
admin
handle
LEGO-GANDI
id
111111
bill
handle
LEGO-GANDI
id
111111
tech
handle
LEGO-GANDI
id
111111
reseller
nameservers
a.dns.gandi.net
b.dns.gandi.net
c.dns.gandi.net
date_restore_end
20170501T02:04:06
id
2222222
authinfo
ABCDABCDAB
status
clientTransferProhibited
serverTransferProhibited
tags
date_hold_end
20170401T02:04:06
services
gandidns
gandimail
date_pending_delete_end
20170506T02:04:06
zone_id
1234567
date_renew_begin
20120101T00:00:00
fqdn
example.com
autorenew
date_registry_creation
20150215T02:04:06
tld
org
date_created
20150215T03:04:06
`,
// CleanUp Request->Response 2 (deleteZone)
`
domain.zone.delete
123412341234123412341234
7654321
`: `
1
`,
}