mirror of
https://github.com/go-acme/lego.git
synced 2025-01-03 07:19:39 +02:00
rfc2136: add support for tsig-keygen generated file (#2330)
Co-authored-by: Dominik Menke <git@dmke.org>
This commit is contained in:
parent
f8db554820
commit
f514292c46
@ -2428,9 +2428,9 @@ func displayDNSHelp(w io.Writer, name string) error {
|
||||
|
||||
ew.writeln(`Credentials:`)
|
||||
ew.writeln(` - "RFC2136_NAMESERVER": Network address in the form "host" or "host:port"`)
|
||||
ew.writeln(` - "RFC2136_TSIG_ALGORITHM": TSIG algorithm. See [miekg/dns#tsig.go](https://github.com/miekg/dns/blob/master/tsig.go) for supported values. To disable TSIG authentication, leave the 'RFC2136_TSIG*' variables unset.`)
|
||||
ew.writeln(` - "RFC2136_TSIG_KEY": Name of the secret key as defined in DNS server configuration. To disable TSIG authentication, leave the 'RFC2136_TSIG*' variables unset.`)
|
||||
ew.writeln(` - "RFC2136_TSIG_SECRET": Secret key payload. To disable TSIG authentication, leave the' RFC2136_TSIG*' variables unset.`)
|
||||
ew.writeln(` - "RFC2136_TSIG_ALGORITHM": TSIG algorithm. See [miekg/dns#tsig.go](https://github.com/miekg/dns/blob/master/tsig.go) for supported values. To disable TSIG authentication, leave the 'RFC2136_TSIG_KEY' or 'RFC2136_TSIG_SECRET' variables unset.`)
|
||||
ew.writeln(` - "RFC2136_TSIG_KEY": Name of the secret key as defined in DNS server configuration. To disable TSIG authentication, leave the 'RFC2136_TSIG_KEY' variable unset.`)
|
||||
ew.writeln(` - "RFC2136_TSIG_SECRET": Secret key payload. To disable TSIG authentication, leave the 'RFC2136_TSIG_SECRET' variable unset.`)
|
||||
ew.writeln()
|
||||
|
||||
ew.writeln(`Additional Configuration:`)
|
||||
@ -2438,6 +2438,7 @@ func displayDNSHelp(w io.Writer, name string) error {
|
||||
ew.writeln(` - "RFC2136_POLLING_INTERVAL": Time between DNS propagation check`)
|
||||
ew.writeln(` - "RFC2136_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`)
|
||||
ew.writeln(` - "RFC2136_SEQUENCE_INTERVAL": Time between sequential requests`)
|
||||
ew.writeln(` - "RFC2136_TSIG_FILE": Path to a key file generated by tsig-keygen`)
|
||||
ew.writeln(` - "RFC2136_TTL": The TTL of the TXT record used for the DNS challenge`)
|
||||
|
||||
ew.writeln()
|
||||
|
@ -27,20 +27,18 @@ Here is an example bash command using the RFC2136 provider:
|
||||
|
||||
```bash
|
||||
RFC2136_NAMESERVER=127.0.0.1 \
|
||||
RFC2136_TSIG_KEY=lego \
|
||||
RFC2136_TSIG_KEY=example.com \
|
||||
RFC2136_TSIG_ALGORITHM=hmac-sha256. \
|
||||
RFC2136_TSIG_SECRET=YWJjZGVmZGdoaWprbG1ub3BxcnN0dXZ3eHl6MTIzNDU= \
|
||||
lego --email you@example.com --dns rfc2136 -d '*.example.com' -d example.com run
|
||||
|
||||
## ---
|
||||
|
||||
keyname=lego; keyfile=lego.key; tsig-keygen $keyname > $keyfile
|
||||
keyname=example.com; keyfile=example.com.key; tsig-keygen $keyname > $keyfile
|
||||
|
||||
RFC2136_NAMESERVER=127.0.0.1 \
|
||||
RFC2136_TSIG_KEY="$keyname" \
|
||||
RFC2136_TSIG_ALGORITHM="$( awk -F'[ ";]' '/algorithm/ { print $2 }' $keyfile )." \
|
||||
RFC2136_TSIG_SECRET="$( awk -F'[ ";]' '/secret/ { print $3 }' $keyfile )" \
|
||||
lego --email you@example.com --dns rfc2136 d "*.example.com" -d example.com run
|
||||
RFC2136_TSIG_FILE="$keyfile" \
|
||||
lego --email you@example.com --dns rfc2136 -d '*.example.com' -d example.com run
|
||||
```
|
||||
|
||||
|
||||
@ -51,9 +49,9 @@ lego --email you@example.com --dns rfc2136 d "*.example.com" -d example.com run
|
||||
| Environment Variable Name | Description |
|
||||
|-----------------------|-------------|
|
||||
| `RFC2136_NAMESERVER` | Network address in the form "host" or "host:port" |
|
||||
| `RFC2136_TSIG_ALGORITHM` | TSIG algorithm. See [miekg/dns#tsig.go](https://github.com/miekg/dns/blob/master/tsig.go) for supported values. To disable TSIG authentication, leave the `RFC2136_TSIG*` variables unset. |
|
||||
| `RFC2136_TSIG_KEY` | Name of the secret key as defined in DNS server configuration. To disable TSIG authentication, leave the `RFC2136_TSIG*` variables unset. |
|
||||
| `RFC2136_TSIG_SECRET` | Secret key payload. To disable TSIG authentication, leave the` RFC2136_TSIG*` variables unset. |
|
||||
| `RFC2136_TSIG_ALGORITHM` | TSIG algorithm. See [miekg/dns#tsig.go](https://github.com/miekg/dns/blob/master/tsig.go) for supported values. To disable TSIG authentication, leave the `RFC2136_TSIG_KEY` or `RFC2136_TSIG_SECRET` variables unset. |
|
||||
| `RFC2136_TSIG_KEY` | Name of the secret key as defined in DNS server configuration. To disable TSIG authentication, leave the `RFC2136_TSIG_KEY` variable unset. |
|
||||
| `RFC2136_TSIG_SECRET` | Secret key payload. To disable TSIG authentication, leave the `RFC2136_TSIG_SECRET` variable unset. |
|
||||
|
||||
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
|
||||
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
|
||||
@ -67,6 +65,7 @@ More information [here]({{% ref "dns#configuration-and-credentials" %}}).
|
||||
| `RFC2136_POLLING_INTERVAL` | Time between DNS propagation check |
|
||||
| `RFC2136_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation |
|
||||
| `RFC2136_SEQUENCE_INTERVAL` | Time between sequential requests |
|
||||
| `RFC2136_TSIG_FILE` | Path to a key file generated by tsig-keygen |
|
||||
| `RFC2136_TTL` | The TTL of the TXT record used for the DNS challenge |
|
||||
|
||||
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
|
||||
|
@ -0,0 +1,4 @@
|
||||
key "example.com" {
|
||||
algorithm;
|
||||
secret "TCG5A6/lOHUGbW0e/9RYYbzWDFMlj1pIxCvybLBayBg=";
|
||||
};
|
4
providers/dns/rfc2136/internal/fixtures/invalid_key.conf
Normal file
4
providers/dns/rfc2136/internal/fixtures/invalid_key.conf
Normal file
@ -0,0 +1,4 @@
|
||||
key {
|
||||
algorithm hmac-sha256;
|
||||
secret "TCG5A6/lOHUGbW0e/9RYYbzWDFMlj1pIxCvybLBayBg=";
|
||||
};
|
3
providers/dns/rfc2136/internal/fixtures/mising_algo.conf
Normal file
3
providers/dns/rfc2136/internal/fixtures/mising_algo.conf
Normal file
@ -0,0 +1,3 @@
|
||||
key "example.com" {
|
||||
secret "TCG5A6/lOHUGbW0e/9RYYbzWDFMlj1pIxCvybLBayBg=";
|
||||
};
|
@ -0,0 +1,3 @@
|
||||
key "example.com" {
|
||||
algorithm hmac-sha256;
|
||||
};
|
4
providers/dns/rfc2136/internal/fixtures/sample.conf
Normal file
4
providers/dns/rfc2136/internal/fixtures/sample.conf
Normal file
@ -0,0 +1,4 @@
|
||||
key "example.com" {
|
||||
algorithm hmac-sha256;
|
||||
secret "TCG5A6/lOHUGbW0e/9RYYbzWDFMlj1pIxCvybLBayBg=";
|
||||
};
|
9
providers/dns/rfc2136/internal/fixtures/text_after.conf
Normal file
9
providers/dns/rfc2136/internal/fixtures/text_after.conf
Normal file
@ -0,0 +1,9 @@
|
||||
key "example.com" {
|
||||
algorithm hmac-sha256;
|
||||
secret "TCG5A6/lOHUGbW0e/9RYYbzWDFMlj1pIxCvybLBayBg=";
|
||||
};
|
||||
|
||||
key "example.org" {
|
||||
algorithm hmac-sha512;
|
||||
secret "v6CkK3gop6HXj4+dcWiLXLGSYKVY5J1cTMjDsdl/Ah9B8aWfTgjwFBoHHyiHWSyvwWPDuEIRs2Pqm8nedca4+g==";
|
||||
};
|
8
providers/dns/rfc2136/internal/fixtures/text_before.conf
Normal file
8
providers/dns/rfc2136/internal/fixtures/text_before.conf
Normal file
@ -0,0 +1,8 @@
|
||||
foo {
|
||||
bar example;
|
||||
};
|
||||
|
||||
key "example.com" {
|
||||
algorithm hmac-sha256;
|
||||
secret "TCG5A6/lOHUGbW0e/9RYYbzWDFMlj1pIxCvybLBayBg=";
|
||||
};
|
10
providers/dns/rfc2136/internal/readme.md
Normal file
10
providers/dns/rfc2136/internal/readme.md
Normal file
@ -0,0 +1,10 @@
|
||||
# TSIG Key File
|
||||
|
||||
How to generate example:
|
||||
|
||||
```console
|
||||
$ docker run --rm -it -v $(pwd):/app -w /app alpine sh
|
||||
/app # apk add bind
|
||||
/app # tsig-keygen example.com > sample1.conf
|
||||
/app # tsig-keygen -a hmac-sha512 example.com > sample2.conf
|
||||
```
|
89
providers/dns/rfc2136/internal/tsigkey.go
Normal file
89
providers/dns/rfc2136/internal/tsigkey.go
Normal file
@ -0,0 +1,89 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Key struct {
|
||||
Name string
|
||||
Algorithm string
|
||||
Secret string
|
||||
}
|
||||
|
||||
// ReadTSIGFile reads TSIG key file generated with `tsig-keygen`.
|
||||
func ReadTSIGFile(filename string) (*Key, error) {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open file: %w", err)
|
||||
}
|
||||
|
||||
defer func() { _ = file.Close() }()
|
||||
|
||||
key := &Key{}
|
||||
|
||||
var read bool
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(strings.TrimSuffix(scanner.Text(), ";"))
|
||||
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if read && line == "}" {
|
||||
break
|
||||
}
|
||||
|
||||
fields := strings.Fields(line)
|
||||
|
||||
switch {
|
||||
case fields[0] == "key":
|
||||
read = true
|
||||
|
||||
if len(fields) != 3 {
|
||||
return nil, fmt.Errorf("invalid key line: %s", line)
|
||||
}
|
||||
|
||||
key.Name = safeUnquote(fields[1])
|
||||
|
||||
case !read:
|
||||
continue
|
||||
|
||||
default:
|
||||
if len(fields) != 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
v := safeUnquote(fields[1])
|
||||
|
||||
switch safeUnquote(fields[0]) {
|
||||
case "algorithm":
|
||||
key.Algorithm = v
|
||||
case "secret":
|
||||
key.Secret = v
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func safeUnquote(v string) string {
|
||||
if len(v) < 2 {
|
||||
// empty or single character string
|
||||
return v
|
||||
}
|
||||
|
||||
if v[0] == '"' && v[len(v)-1] == '"' {
|
||||
// string wrapped in quotes
|
||||
return v[1 : len(v)-1]
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
95
providers/dns/rfc2136/internal/tsigkey_test.go
Normal file
95
providers/dns/rfc2136/internal/tsigkey_test.go
Normal file
@ -0,0 +1,95 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestReadTSIGFile(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
filename string
|
||||
expected *Key
|
||||
}{
|
||||
{
|
||||
desc: "basic",
|
||||
filename: "sample.conf",
|
||||
expected: &Key{Name: "example.com", Algorithm: "hmac-sha256", Secret: "TCG5A6/lOHUGbW0e/9RYYbzWDFMlj1pIxCvybLBayBg="},
|
||||
},
|
||||
{
|
||||
desc: "data before the key",
|
||||
filename: "text_before.conf",
|
||||
expected: &Key{Name: "example.com", Algorithm: "hmac-sha256", Secret: "TCG5A6/lOHUGbW0e/9RYYbzWDFMlj1pIxCvybLBayBg="},
|
||||
},
|
||||
{
|
||||
desc: "data after the key",
|
||||
filename: "text_after.conf",
|
||||
expected: &Key{Name: "example.com", Algorithm: "hmac-sha256", Secret: "TCG5A6/lOHUGbW0e/9RYYbzWDFMlj1pIxCvybLBayBg="},
|
||||
},
|
||||
{
|
||||
desc: "ignore missing secret",
|
||||
filename: "missing_secret.conf",
|
||||
expected: &Key{Name: "example.com", Algorithm: "hmac-sha256"},
|
||||
},
|
||||
{
|
||||
desc: "ignore missing algorithm",
|
||||
filename: "mising_algo.conf",
|
||||
expected: &Key{Name: "example.com", Secret: "TCG5A6/lOHUGbW0e/9RYYbzWDFMlj1pIxCvybLBayBg="},
|
||||
},
|
||||
{
|
||||
desc: "ignore invalid field format",
|
||||
filename: "invalid_field.conf",
|
||||
expected: &Key{Name: "example.com", Secret: "TCG5A6/lOHUGbW0e/9RYYbzWDFMlj1pIxCvybLBayBg="},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
key, err := ReadTSIGFile(filepath.Join("fixtures", test.filename))
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, test.expected, key)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadTSIGFile_error(t *testing.T) {
|
||||
if runtime.GOOS != "linux" {
|
||||
// Because error messages are different on Windows.
|
||||
t.Skip("only for UNIX systems")
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
desc string
|
||||
filename string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
desc: "missing file",
|
||||
filename: "missing.conf",
|
||||
expected: "open file: open fixtures/missing.conf: no such file or directory",
|
||||
},
|
||||
{
|
||||
desc: "invalid key format",
|
||||
filename: "invalid_key.conf",
|
||||
expected: "invalid key line: key {",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := ReadTSIGFile(filepath.Join("fixtures", test.filename))
|
||||
require.Error(t, err)
|
||||
|
||||
require.EqualError(t, err, test.expected)
|
||||
})
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||
"github.com/go-acme/lego/v4/platform/config/env"
|
||||
"github.com/go-acme/lego/v4/providers/dns/rfc2136/internal"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
@ -17,11 +18,14 @@ import (
|
||||
const (
|
||||
envNamespace = "RFC2136_"
|
||||
|
||||
EnvTSIGFile = envNamespace + "TSIG_FILE"
|
||||
|
||||
EnvTSIGKey = envNamespace + "TSIG_KEY"
|
||||
EnvTSIGSecret = envNamespace + "TSIG_SECRET"
|
||||
EnvTSIGAlgorithm = envNamespace + "TSIG_ALGORITHM"
|
||||
EnvNameserver = envNamespace + "NAMESERVER"
|
||||
EnvDNSTimeout = envNamespace + "DNS_TIMEOUT"
|
||||
|
||||
EnvNameserver = envNamespace + "NAMESERVER"
|
||||
EnvDNSTimeout = envNamespace + "DNS_TIMEOUT"
|
||||
|
||||
EnvTTL = envNamespace + "TTL"
|
||||
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
|
||||
@ -31,10 +35,14 @@ const (
|
||||
|
||||
// Config is used to configure the creation of the DNSProvider.
|
||||
type Config struct {
|
||||
Nameserver string
|
||||
TSIGAlgorithm string
|
||||
TSIGKey string
|
||||
TSIGSecret string
|
||||
Nameserver string
|
||||
|
||||
TSIGFile string
|
||||
|
||||
TSIGAlgorithm string
|
||||
TSIGKey string
|
||||
TSIGSecret string
|
||||
|
||||
PropagationTimeout time.Duration
|
||||
PollingInterval time.Duration
|
||||
TTL int
|
||||
@ -76,6 +84,9 @@ func NewDNSProvider() (*DNSProvider, error) {
|
||||
|
||||
config := NewDefaultConfig()
|
||||
config.Nameserver = values[EnvNameserver]
|
||||
|
||||
config.TSIGFile = env.GetOrDefaultString(EnvTSIGFile, "")
|
||||
|
||||
config.TSIGKey = env.GetOrFile(EnvTSIGKey)
|
||||
config.TSIGSecret = env.GetOrFile(EnvTSIGSecret)
|
||||
|
||||
@ -92,8 +103,15 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
return nil, errors.New("rfc2136: nameserver missing")
|
||||
}
|
||||
|
||||
if config.TSIGAlgorithm == "" {
|
||||
config.TSIGAlgorithm = dns.HmacSHA1
|
||||
if config.TSIGFile != "" {
|
||||
key, err := internal.ReadTSIGFile(config.TSIGFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("rfc2136: read TSIG file %s: %w", config.TSIGFile, err)
|
||||
}
|
||||
|
||||
config.TSIGAlgorithm = key.Algorithm
|
||||
config.TSIGKey = key.Name
|
||||
config.TSIGSecret = key.Secret
|
||||
}
|
||||
|
||||
// Append the default DNS port if none is specified.
|
||||
@ -108,6 +126,23 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
if config.TSIGKey == "" || config.TSIGSecret == "" {
|
||||
config.TSIGKey = ""
|
||||
config.TSIGSecret = ""
|
||||
} else {
|
||||
// zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
|
||||
config.TSIGKey = strings.ToLower(dns.Fqdn(config.TSIGKey))
|
||||
}
|
||||
|
||||
if config.TSIGAlgorithm == "" {
|
||||
config.TSIGAlgorithm = dns.HmacSHA1
|
||||
} else {
|
||||
// To be compatible with https://github.com/miekg/dns/blob/master/tsig.go
|
||||
config.TSIGAlgorithm = dns.Fqdn(config.TSIGAlgorithm)
|
||||
}
|
||||
|
||||
switch config.TSIGAlgorithm {
|
||||
case dns.HmacSHA1, dns.HmacSHA224, dns.HmacSHA256, dns.HmacSHA384, dns.HmacSHA512:
|
||||
// valid algorithm
|
||||
default:
|
||||
return nil, fmt.Errorf("rfc2136: unsupported TSIG algorithm: %s", config.TSIGAlgorithm)
|
||||
}
|
||||
|
||||
return &DNSProvider{config: config}, nil
|
||||
@ -179,13 +214,10 @@ func (d *DNSProvider) changeRecord(action, fqdn, value string, ttl int) error {
|
||||
|
||||
// TSIG authentication / msg signing
|
||||
if d.config.TSIGKey != "" && d.config.TSIGSecret != "" {
|
||||
key := strings.ToLower(dns.Fqdn(d.config.TSIGKey))
|
||||
alg := dns.Fqdn(d.config.TSIGAlgorithm)
|
||||
m.SetTsig(key, alg, 300, time.Now().Unix())
|
||||
m.SetTsig(d.config.TSIGKey, d.config.TSIGAlgorithm, 300, time.Now().Unix())
|
||||
|
||||
// secret(s) for Tsig map[<zonename>]<base64 secret>,
|
||||
// zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
|
||||
c.TsigSecret = map[string]string{key: d.config.TSIGSecret}
|
||||
// Secret(s) for TSIG map[<zonename>]<base64 secret>.
|
||||
c.TsigSecret = map[string]string{d.config.TSIGKey: d.config.TSIGSecret}
|
||||
}
|
||||
|
||||
// Send the query
|
||||
|
@ -6,29 +6,28 @@ Since = "v0.3.0"
|
||||
|
||||
Example = '''
|
||||
RFC2136_NAMESERVER=127.0.0.1 \
|
||||
RFC2136_TSIG_KEY=lego \
|
||||
RFC2136_TSIG_KEY=example.com \
|
||||
RFC2136_TSIG_ALGORITHM=hmac-sha256. \
|
||||
RFC2136_TSIG_SECRET=YWJjZGVmZGdoaWprbG1ub3BxcnN0dXZ3eHl6MTIzNDU= \
|
||||
lego --email you@example.com --dns rfc2136 -d '*.example.com' -d example.com run
|
||||
|
||||
## ---
|
||||
|
||||
keyname=lego; keyfile=lego.key; tsig-keygen $keyname > $keyfile
|
||||
keyname=example.com; keyfile=example.com.key; tsig-keygen $keyname > $keyfile
|
||||
|
||||
RFC2136_NAMESERVER=127.0.0.1 \
|
||||
RFC2136_TSIG_KEY="$keyname" \
|
||||
RFC2136_TSIG_ALGORITHM="$( awk -F'[ ";]' '/algorithm/ { print $2 }' $keyfile )." \
|
||||
RFC2136_TSIG_SECRET="$( awk -F'[ ";]' '/secret/ { print $3 }' $keyfile )" \
|
||||
lego --email you@example.com --dns rfc2136 d "*.example.com" -d example.com run
|
||||
RFC2136_TSIG_FILE="$keyfile" \
|
||||
lego --email you@example.com --dns rfc2136 -d '*.example.com' -d example.com run
|
||||
'''
|
||||
|
||||
[Configuration]
|
||||
[Configuration.Credentials]
|
||||
RFC2136_TSIG_KEY = "Name of the secret key as defined in DNS server configuration. To disable TSIG authentication, leave the `RFC2136_TSIG*` variables unset."
|
||||
RFC2136_TSIG_SECRET = "Secret key payload. To disable TSIG authentication, leave the` RFC2136_TSIG*` variables unset."
|
||||
RFC2136_TSIG_ALGORITHM = "TSIG algorithm. See [miekg/dns#tsig.go](https://github.com/miekg/dns/blob/master/tsig.go) for supported values. To disable TSIG authentication, leave the `RFC2136_TSIG*` variables unset."
|
||||
RFC2136_TSIG_KEY = "Name of the secret key as defined in DNS server configuration. To disable TSIG authentication, leave the `RFC2136_TSIG_KEY` variable unset."
|
||||
RFC2136_TSIG_SECRET = "Secret key payload. To disable TSIG authentication, leave the `RFC2136_TSIG_SECRET` variable unset."
|
||||
RFC2136_TSIG_ALGORITHM = "TSIG algorithm. See [miekg/dns#tsig.go](https://github.com/miekg/dns/blob/master/tsig.go) for supported values. To disable TSIG authentication, leave the `RFC2136_TSIG_KEY` or `RFC2136_TSIG_SECRET` variables unset."
|
||||
RFC2136_NAMESERVER = 'Network address in the form "host" or "host:port"'
|
||||
[Configuration.Additional]
|
||||
RFC2136_TSIG_FILE = "Path to a key file generated by tsig-keygen"
|
||||
RFC2136_POLLING_INTERVAL = "Time between DNS propagation check"
|
||||
RFC2136_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation"
|
||||
RFC2136_TTL = "The TTL of the TXT record used for the DNS challenge"
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||
"github.com/go-acme/lego/v4/platform/tester"
|
||||
"github.com/miekg/dns"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -26,6 +27,142 @@ const (
|
||||
fakeTsigSecret = "IwBTJx9wrDp4Y1RyC3H0gA=="
|
||||
)
|
||||
|
||||
const envDomain = envNamespace + "DOMAIN"
|
||||
|
||||
var envTest = tester.NewEnvTest(
|
||||
EnvTSIGFile,
|
||||
EnvTSIGKey,
|
||||
EnvTSIGSecret,
|
||||
EnvTSIGAlgorithm,
|
||||
EnvNameserver,
|
||||
EnvDNSTimeout,
|
||||
).WithDomain(envDomain)
|
||||
|
||||
func TestNewDNSProvider(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
envVars map[string]string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
desc: "success",
|
||||
envVars: map[string]string{
|
||||
EnvNameserver: "example.com",
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "missing nameserver",
|
||||
envVars: map[string]string{
|
||||
EnvNameserver: "",
|
||||
},
|
||||
expected: "rfc2136: some credentials information are missing: RFC2136_NAMESERVER",
|
||||
},
|
||||
{
|
||||
desc: "invalid algorithm",
|
||||
envVars: map[string]string{
|
||||
EnvNameserver: "example.com",
|
||||
EnvTSIGKey: "",
|
||||
EnvTSIGSecret: "",
|
||||
EnvTSIGAlgorithm: "foo",
|
||||
},
|
||||
expected: "rfc2136: unsupported TSIG algorithm: foo.",
|
||||
},
|
||||
{
|
||||
desc: "valid TSIG file",
|
||||
envVars: map[string]string{
|
||||
EnvNameserver: "example.com",
|
||||
EnvTSIGFile: "./internal/fixtures/sample.conf",
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "invalid TSIG file",
|
||||
envVars: map[string]string{
|
||||
EnvNameserver: "example.com",
|
||||
EnvTSIGFile: "./internal/fixtures/invalid_key.conf",
|
||||
},
|
||||
expected: "rfc2136: read TSIG file ./internal/fixtures/invalid_key.conf: invalid key line: 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 test.expected == "" {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, p)
|
||||
require.NotNil(t, p.config)
|
||||
} else {
|
||||
require.EqualError(t, err, test.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewDNSProviderConfig(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
expected string
|
||||
nameserver string
|
||||
tsigFile string
|
||||
tsigAlgorithm string
|
||||
tsigKey string
|
||||
tsigSecret string
|
||||
}{
|
||||
{
|
||||
desc: "success",
|
||||
nameserver: "example.com",
|
||||
},
|
||||
{
|
||||
desc: "missing nameserver",
|
||||
expected: "rfc2136: nameserver missing",
|
||||
},
|
||||
{
|
||||
desc: "invalid algorithm",
|
||||
nameserver: "example.com",
|
||||
tsigAlgorithm: "foo",
|
||||
expected: "rfc2136: unsupported TSIG algorithm: foo.",
|
||||
},
|
||||
{
|
||||
desc: "valid TSIG file",
|
||||
nameserver: "example.com",
|
||||
tsigFile: "./internal/fixtures/sample.conf",
|
||||
},
|
||||
{
|
||||
desc: "invalid TSIG file",
|
||||
nameserver: "example.com",
|
||||
tsigFile: "./internal/fixtures/invalid_key.conf",
|
||||
expected: "rfc2136: read TSIG file ./internal/fixtures/invalid_key.conf: invalid key line: key {",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
config := NewDefaultConfig()
|
||||
config.Nameserver = test.nameserver
|
||||
config.TSIGFile = test.tsigFile
|
||||
config.TSIGAlgorithm = test.tsigAlgorithm
|
||||
config.TSIGKey = test.tsigKey
|
||||
config.TSIGSecret = test.tsigSecret
|
||||
|
||||
p, err := NewDNSProviderConfig(config)
|
||||
|
||||
if test.expected == "" {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, p)
|
||||
require.NotNil(t, p.config)
|
||||
} else {
|
||||
require.EqualError(t, err, test.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanaryLocalTestServer(t *testing.T) {
|
||||
dns01.ClearFqdnCache()
|
||||
dns.HandleFunc("example.com.", serverHandlerHello)
|
||||
|
Loading…
Reference in New Issue
Block a user