1
0
mirror of https://github.com/StackExchange/dnscontrol.git synced 2024-05-11 05:55:12 +00:00

BIND: Improve SOA serial number handling (#651)

* github.com/miekg/dns
* Greatly simplify the logic for handling serial numbers. Related code was all over the place. Now it is abstracted into one testable method makeSoa. This simplifies code in many other places.
* Update docs/_providers/bind.md: Edit old text. Add SOA description.
* SOA records are now treated like any other record internally. You still can't specify them in dnsconfig.js, but that's by design.
* The URL for issue 491 was wrong in many places
* BIND: Clarify GENERATE_ZONEFILE message
This commit is contained in:
Tom Limoncelli
2020-02-23 13:58:49 -05:00
committed by GitHub
parent 3c41a39252
commit 9812ecd9ff
60 changed files with 708 additions and 254 deletions

147
providers/bind/soa_test.go Normal file
View File

@ -0,0 +1,147 @@
package bind
import (
"fmt"
"testing"
"time"
"github.com/StackExchange/dnscontrol/v2/models"
)
func Test_makeSoa(t *testing.T) {
origin := "example.com"
var tests = []struct {
def *SoaInfo
existing *models.RecordConfig
desired *models.RecordConfig
expectedSoa *models.RecordConfig
expectedSerial uint32
}{
{
// If everything is blank, the hard-coded defaults should kick in.
&SoaInfo{"", "", 0, 0, 0, 0, 0},
&models.RecordConfig{Target: "", SoaMbox: "", SoaSerial: 0, SoaRefresh: 0, SoaRetry: 0, SoaExpire: 0, SoaMinttl: 0},
&models.RecordConfig{Target: "", SoaMbox: "", SoaSerial: 0, SoaRefresh: 0, SoaRetry: 0, SoaExpire: 0, SoaMinttl: 0},
&models.RecordConfig{Target: "DEFAULT_NOT_SET.", SoaMbox: "DEFAULT_NOT_SET.", SoaSerial: 1, SoaRefresh: 3600, SoaRetry: 600, SoaExpire: 604800, SoaMinttl: 1440},
2019022301,
},
{
// If everything is filled, leave the desired values in place.
&SoaInfo{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5},
&models.RecordConfig{Target: "a", SoaMbox: "aa", SoaSerial: 10, SoaRefresh: 11, SoaRetry: 12, SoaExpire: 13, SoaMinttl: 14},
&models.RecordConfig{Target: "b", SoaMbox: "bb", SoaSerial: 15, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19},
&models.RecordConfig{Target: "b", SoaMbox: "bb", SoaSerial: 15, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19},
2019022301,
},
{
// Test incrementing serial.
&SoaInfo{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5},
&models.RecordConfig{Target: "a", SoaMbox: "aa", SoaSerial: 2019022301, SoaRefresh: 11, SoaRetry: 12, SoaExpire: 13, SoaMinttl: 14},
&models.RecordConfig{Target: "b", SoaMbox: "bb", SoaSerial: 0, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19},
&models.RecordConfig{Target: "b", SoaMbox: "bb", SoaSerial: 2019022301, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19},
2019022302,
},
{
// Test incrementing serial_2.
&SoaInfo{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5},
&models.RecordConfig{Target: "a", SoaMbox: "aa", SoaSerial: 0, SoaRefresh: 11, SoaRetry: 12, SoaExpire: 13, SoaMinttl: 14},
&models.RecordConfig{Target: "b", SoaMbox: "bb", SoaSerial: 2019022304, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19},
&models.RecordConfig{Target: "b", SoaMbox: "bb", SoaSerial: 2019022304, SoaRefresh: 16, SoaRetry: 17, SoaExpire: 18, SoaMinttl: 19},
2019022305,
},
{
// If there are gaps in existing or desired, fill in as appropriate.
&SoaInfo{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5},
&models.RecordConfig{Target: "", SoaMbox: "aa", SoaSerial: 0, SoaRefresh: 11, SoaRetry: 0, SoaExpire: 13, SoaMinttl: 0},
&models.RecordConfig{Target: "b", SoaMbox: "", SoaSerial: 15, SoaRefresh: 0, SoaRetry: 17, SoaExpire: 0, SoaMinttl: 19},
&models.RecordConfig{Target: "b", SoaMbox: "aa", SoaSerial: 15, SoaRefresh: 11, SoaRetry: 17, SoaExpire: 13, SoaMinttl: 19},
2019022301,
},
{
// Gaps + existing==nil
&SoaInfo{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5},
nil,
&models.RecordConfig{Target: "b", SoaMbox: "", SoaSerial: 15, SoaRefresh: 0, SoaRetry: 17, SoaExpire: 0, SoaMinttl: 19},
&models.RecordConfig{Target: "b", SoaMbox: "root.example.com", SoaSerial: 15, SoaRefresh: 2, SoaRetry: 17, SoaExpire: 4, SoaMinttl: 19},
2019022301,
},
{
// Gaps + desired==nil
// NB(tom): In the code as of 2020-02-23, desired will never be nil.
&SoaInfo{"ns.example.com", "root.example.com", 1, 2, 3, 4, 5},
&models.RecordConfig{Target: "", SoaMbox: "aa", SoaSerial: 0, SoaRefresh: 11, SoaRetry: 0, SoaExpire: 13, SoaMinttl: 0},
nil,
&models.RecordConfig{Target: "ns.example.com", SoaMbox: "aa", SoaSerial: 1, SoaRefresh: 11, SoaRetry: 3, SoaExpire: 13, SoaMinttl: 5},
2019022301,
},
}
// Fake out the tests so they think today is 2019-02-23
nowFunc = func() time.Time {
fakeToday, _ := time.Parse("20060102", "20190223")
return fakeToday
}
for i, tst := range tests {
if tst.existing != nil {
tst.existing.SetLabel("@", origin)
tst.existing.Type = "SOA"
}
if tst.desired != nil {
tst.desired.SetLabel("@", origin)
tst.desired.Type = "SOA"
}
tst.expectedSoa.SetLabel("@", origin)
tst.expectedSoa.Type = "SOA"
r1, r2 := makeSoa(origin, tst.def, tst.existing, tst.desired)
if !areEqualSoa(r1, tst.expectedSoa) {
t.Fatalf("Test %d soa:\nExpected (%v)\n got (%v)\n", i, tst.expectedSoa.String(), r1.String())
}
if r2 != tst.expectedSerial {
t.Fatalf("Test:%d soa: Expected (%v) got (%v)\n", i, tst.expectedSerial, r2)
}
}
}
func areEqualSoa(r1, r2 *models.RecordConfig) bool {
if r1.NameFQDN != r2.NameFQDN {
fmt.Printf("ERROR: fqdn %q != %q\n", r1.NameFQDN, r2.NameFQDN)
return false
}
if r1.Name != r2.Name {
fmt.Printf("ERROR: name %q != %q\n", r1.Name, r2.Name)
return false
}
if r1.Target != r2.Target {
fmt.Printf("ERROR: target %q != %q\n", r1.Target, r2.Target)
return false
}
if r1.SoaMbox != r2.SoaMbox {
fmt.Printf("ERROR: mbox %v != %v\n", r1.SoaMbox, r2.SoaMbox)
return false
}
if r1.SoaSerial != r2.SoaSerial {
fmt.Printf("ERROR: serial %v != %v\n", r1.SoaSerial, r2.SoaSerial)
return false
}
if r1.SoaRefresh != r2.SoaRefresh {
fmt.Printf("ERROR: refresh %v != %v\n", r1.SoaRefresh, r2.SoaRefresh)
return false
}
if r1.SoaRetry != r2.SoaRetry {
fmt.Printf("ERROR: retry %v != %v\n", r1.SoaRetry, r2.SoaRetry)
return false
}
if r1.SoaExpire != r2.SoaExpire {
fmt.Printf("ERROR: expire %v != %v\n", r1.SoaExpire, r2.SoaExpire)
return false
}
if r1.SoaMinttl != r2.SoaMinttl {
fmt.Printf("ERROR: minttl %v != %v\n", r1.SoaMinttl, r2.SoaMinttl)
return false
}
return true
}