mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
Expect SOA mailbox in hostmaster@example.org format instead of hostmaster.example.org (#2037)
Co-authored-by: Yannik Sembritzki <yannik@sembritzki.org> Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
This commit is contained in:
committed by
GitHub
parent
9eacd42b63
commit
dc02d5b74f
@@ -24,12 +24,14 @@ parameter_types:
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
D("example.com", REG_THIRDPARTY, DnsProvider("DNS_BIND"),
|
D("example.com", REG_THIRDPARTY, DnsProvider("DNS_BIND"),
|
||||||
SOA("@", "ns3.example.org.", "hostmaster.example.org.", 3600, 600, 604800, 1440),
|
SOA("@", "ns3.example.org.", "hostmaster@example.org", 3600, 600, 604800, 1440),
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
## Notes
|
The email address should be specified like a normal RFC822/RFC5322 address (user@hostname.com). It will be converted into the required format (e.g. BIND format: `user.hostname.com`) by the provider as required. This has the benefit of being more human-readable plus DNSControl can properly handle escaping and other issues.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
* Previously, the accepted format for the SOA mailbox field was `hostmaster.example.org`. This has been changed to `hostmaster@example.org`
|
||||||
* The serial number is managed automatically. It isn't even a field in `SOA()`.
|
* The serial number is managed automatically. It isn't even a field in `SOA()`.
|
||||||
* Most providers automatically generate SOA records. They will ignore any `SOA()` statements.
|
* Most providers automatically generate SOA records. They will ignore any `SOA()` statements.
|
||||||
|
|
||||||
|
11
pkg/soautil/soautil.go
Normal file
11
pkg/soautil/soautil.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package soautil
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
func RFC5322MailToBind(rfc5322Mail string) string {
|
||||||
|
res := strings.SplitN(rfc5322Mail, "@", 2)
|
||||||
|
user_part, domain_part := res[0], res[1]
|
||||||
|
// RFC-1035 [Section-8]
|
||||||
|
user_part = strings.ReplaceAll(user_part, ".", "\\.")
|
||||||
|
return user_part + "." + domain_part
|
||||||
|
}
|
28
pkg/soautil/soautil_test.go
Normal file
28
pkg/soautil/soautil_test.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package soautil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_RFC5322MailToBind(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
rfc5322Mail string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
rfc5322Mail string
|
||||||
|
bindMail string
|
||||||
|
}{
|
||||||
|
{"0", "hostmaster@example.com", "hostmaster.example.com"},
|
||||||
|
{"1", "admin.dns@example.com", "admin\\.dns.example.com"},
|
||||||
|
{"2", "hostmaster@sub.example.com", "hostmaster.sub.example.com"},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := RFC5322MailToBind(tt.rfc5322Mail); !reflect.DeepEqual(got, tt.bindMail) {
|
||||||
|
t.Errorf("RFC5322MailToBind(%v) = %v, want %v", tt.rfc5322Mail, got, tt.bindMail)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,11 @@
|
|||||||
package bind
|
package bind
|
||||||
|
|
||||||
import "github.com/StackExchange/dnscontrol/v3/models"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/StackExchange/dnscontrol/v3/models"
|
||||||
|
"github.com/StackExchange/dnscontrol/v3/pkg/soautil"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
func makeSoa(origin string, defSoa *SoaDefaults, existing, desired *models.RecordConfig) (*models.RecordConfig, uint32) {
|
func makeSoa(origin string, defSoa *SoaDefaults, existing, desired *models.RecordConfig) (*models.RecordConfig, uint32) {
|
||||||
// Create a SOA record. Take data from desired, existing, default,
|
// Create a SOA record. Take data from desired, existing, default,
|
||||||
@@ -19,10 +24,18 @@ func makeSoa(origin string, defSoa *SoaDefaults, existing, desired *models.Recor
|
|||||||
desired = &models.RecordConfig{}
|
desired = &models.RecordConfig{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
soaMail := firstNonNull(desired.SoaMbox, existing.SoaMbox, defSoa.Mbox, "DEFAULT_NOT_SET.")
|
||||||
|
if strings.Contains(soaMail, "@") {
|
||||||
|
soaMail = soautil.RFC5322MailToBind(soaMail)
|
||||||
|
} else {
|
||||||
|
fmt.Println("WARNING: SOA hostmaster address must be in the format hostmaster@example.com")
|
||||||
|
fmt.Println("WARNING: hostmaster.example.com is deprecated and will be dropped in a future version")
|
||||||
|
}
|
||||||
|
|
||||||
soaRec.TTL = firstNonZero(desired.TTL, defSoa.TTL, existing.TTL, models.DefaultTTL)
|
soaRec.TTL = firstNonZero(desired.TTL, defSoa.TTL, existing.TTL, models.DefaultTTL)
|
||||||
soaRec.SetTargetSOA(
|
soaRec.SetTargetSOA(
|
||||||
firstNonNull(desired.GetTargetField(), existing.GetTargetField(), defSoa.Ns, "DEFAULT_NOT_SET."),
|
firstNonNull(desired.GetTargetField(), existing.GetTargetField(), defSoa.Ns, "DEFAULT_NOT_SET."),
|
||||||
firstNonNull(desired.SoaMbox, existing.SoaMbox, defSoa.Mbox, "DEFAULT_NOT_SET."),
|
soaMail,
|
||||||
firstNonZero(desired.SoaSerial, existing.SoaSerial, defSoa.Serial, 1),
|
firstNonZero(desired.SoaSerial, existing.SoaSerial, defSoa.Serial, 1),
|
||||||
firstNonZero(desired.SoaRefresh, existing.SoaRefresh, defSoa.Refresh, 3600),
|
firstNonZero(desired.SoaRefresh, existing.SoaRefresh, defSoa.Refresh, 3600),
|
||||||
firstNonZero(desired.SoaRetry, existing.SoaRetry, defSoa.Retry, 600),
|
firstNonZero(desired.SoaRetry, existing.SoaRetry, defSoa.Retry, 600),
|
||||||
|
@@ -32,7 +32,7 @@ func Test_makeSoa(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
// If everything is filled, leave the desired values in place.
|
// If everything is filled, leave the desired values in place.
|
||||||
&SoaDefaults{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5, models.DefaultTTL},
|
&SoaDefaults{"ns.example.com", "root@example.com", 1, 2, 3, 4, 5, models.DefaultTTL},
|
||||||
mkRC("a", &models.RecordConfig{SoaMbox: "aa", SoaSerial: 10, SoaRefresh: 11, SoaRetry: 12, SoaExpire: 13, SoaMinttl: 14}),
|
mkRC("a", &models.RecordConfig{SoaMbox: "aa", SoaSerial: 10, SoaRefresh: 11, SoaRetry: 12, SoaExpire: 13, SoaMinttl: 14}),
|
||||||
mkRC("b", &models.RecordConfig{SoaMbox: "bb", SoaSerial: 15, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19}),
|
mkRC("b", &models.RecordConfig{SoaMbox: "bb", SoaSerial: 15, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19}),
|
||||||
mkRC("b", &models.RecordConfig{SoaMbox: "bb", SoaSerial: 15, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19}),
|
mkRC("b", &models.RecordConfig{SoaMbox: "bb", SoaSerial: 15, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19}),
|
||||||
@@ -40,7 +40,7 @@ func Test_makeSoa(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Test incrementing serial.
|
// Test incrementing serial.
|
||||||
&SoaDefaults{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5, models.DefaultTTL},
|
&SoaDefaults{"ns.example.com", "root@example.com", 1, 2, 3, 4, 5, models.DefaultTTL},
|
||||||
mkRC("a", &models.RecordConfig{SoaMbox: "aa", SoaSerial: 2019022301, SoaRefresh: 11, SoaRetry: 12, SoaExpire: 13, SoaMinttl: 14}),
|
mkRC("a", &models.RecordConfig{SoaMbox: "aa", SoaSerial: 2019022301, SoaRefresh: 11, SoaRetry: 12, SoaExpire: 13, SoaMinttl: 14}),
|
||||||
mkRC("b", &models.RecordConfig{SoaMbox: "bb", SoaSerial: 0, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19}),
|
mkRC("b", &models.RecordConfig{SoaMbox: "bb", SoaSerial: 0, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19}),
|
||||||
mkRC("b", &models.RecordConfig{SoaMbox: "bb", SoaSerial: 2019022301, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19}),
|
mkRC("b", &models.RecordConfig{SoaMbox: "bb", SoaSerial: 2019022301, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19}),
|
||||||
@@ -48,7 +48,7 @@ func Test_makeSoa(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Test incrementing serial_2.
|
// Test incrementing serial_2.
|
||||||
&SoaDefaults{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5, models.DefaultTTL},
|
&SoaDefaults{"ns.example.com", "root@example.com", 1, 2, 3, 4, 5, models.DefaultTTL},
|
||||||
mkRC("a", &models.RecordConfig{SoaMbox: "aa", SoaSerial: 0, SoaRefresh: 11, SoaRetry: 12, SoaExpire: 13, SoaMinttl: 14}),
|
mkRC("a", &models.RecordConfig{SoaMbox: "aa", SoaSerial: 0, SoaRefresh: 11, SoaRetry: 12, SoaExpire: 13, SoaMinttl: 14}),
|
||||||
mkRC("b", &models.RecordConfig{SoaMbox: "bb", SoaSerial: 2019022304, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19}),
|
mkRC("b", &models.RecordConfig{SoaMbox: "bb", SoaSerial: 2019022304, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19}),
|
||||||
mkRC("b", &models.RecordConfig{SoaMbox: "bb", SoaSerial: 2019022304, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19}),
|
mkRC("b", &models.RecordConfig{SoaMbox: "bb", SoaSerial: 2019022304, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19}),
|
||||||
@@ -56,7 +56,7 @@ func Test_makeSoa(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
// If there are gaps in existing or desired, fill in as appropriate.
|
// If there are gaps in existing or desired, fill in as appropriate.
|
||||||
&SoaDefaults{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5, models.DefaultTTL},
|
&SoaDefaults{"ns.example.com", "root@example.com", 1, 2, 3, 4, 5, models.DefaultTTL},
|
||||||
mkRC("", &models.RecordConfig{SoaMbox: "aa", SoaSerial: 0, SoaRefresh: 11, SoaRetry: 0, SoaExpire: 13, SoaMinttl: 0}),
|
mkRC("", &models.RecordConfig{SoaMbox: "aa", SoaSerial: 0, SoaRefresh: 11, SoaRetry: 0, SoaExpire: 13, SoaMinttl: 0}),
|
||||||
mkRC("b", &models.RecordConfig{SoaMbox: "", SoaSerial: 15, SoaRefresh: 0, SoaRetry: 17, SoaExpire: 0, SoaMinttl: 19}),
|
mkRC("b", &models.RecordConfig{SoaMbox: "", SoaSerial: 15, SoaRefresh: 0, SoaRetry: 17, SoaExpire: 0, SoaMinttl: 19}),
|
||||||
mkRC("b", &models.RecordConfig{SoaMbox: "aa", SoaSerial: 15, SoaRefresh: 11, SoaRetry: 17, SoaExpire: 13, SoaMinttl: 19}),
|
mkRC("b", &models.RecordConfig{SoaMbox: "aa", SoaSerial: 15, SoaRefresh: 11, SoaRetry: 17, SoaExpire: 13, SoaMinttl: 19}),
|
||||||
@@ -64,7 +64,7 @@ func Test_makeSoa(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Gaps + existing==nil
|
// Gaps + existing==nil
|
||||||
&SoaDefaults{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5, models.DefaultTTL},
|
&SoaDefaults{"ns.example.com", "root@example.com", 1, 2, 3, 4, 5, models.DefaultTTL},
|
||||||
nil,
|
nil,
|
||||||
mkRC("b", &models.RecordConfig{SoaMbox: "", SoaSerial: 15, SoaRefresh: 0, SoaRetry: 17, SoaExpire: 0, SoaMinttl: 19}),
|
mkRC("b", &models.RecordConfig{SoaMbox: "", SoaSerial: 15, SoaRefresh: 0, SoaRetry: 17, SoaExpire: 0, SoaMinttl: 19}),
|
||||||
mkRC("b", &models.RecordConfig{SoaMbox: "root.example.com", SoaSerial: 15, SoaRefresh: 2, SoaRetry: 17, SoaExpire: 4, SoaMinttl: 19}),
|
mkRC("b", &models.RecordConfig{SoaMbox: "root.example.com", SoaSerial: 15, SoaRefresh: 2, SoaRetry: 17, SoaExpire: 4, SoaMinttl: 19}),
|
||||||
@@ -73,7 +73,7 @@ func Test_makeSoa(t *testing.T) {
|
|||||||
{
|
{
|
||||||
// Gaps + desired==nil
|
// Gaps + desired==nil
|
||||||
// NB(tom): In the code as of 2020-02-23, desired will never be nil.
|
// NB(tom): In the code as of 2020-02-23, desired will never be nil.
|
||||||
&SoaDefaults{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5, models.DefaultTTL},
|
&SoaDefaults{"ns.example.com", "root@example.com", 1, 2, 3, 4, 5, models.DefaultTTL},
|
||||||
mkRC("", &models.RecordConfig{SoaMbox: "aa", SoaSerial: 0, SoaRefresh: 11, SoaRetry: 0, SoaExpire: 13, SoaMinttl: 0}),
|
mkRC("", &models.RecordConfig{SoaMbox: "aa", SoaSerial: 0, SoaRefresh: 11, SoaRetry: 0, SoaExpire: 13, SoaMinttl: 0}),
|
||||||
nil,
|
nil,
|
||||||
mkRC("ns.example.com", &models.RecordConfig{SoaMbox: "aa", SoaSerial: 1, SoaRefresh: 11, SoaRetry: 3, SoaExpire: 13, SoaMinttl: 5}),
|
mkRC("ns.example.com", &models.RecordConfig{SoaMbox: "aa", SoaSerial: 1, SoaRefresh: 11, SoaRetry: 3, SoaExpire: 13, SoaMinttl: 5}),
|
||||||
|
Reference in New Issue
Block a user