mirror of
https://github.com/netbirdio/netbird.git
synced 2026-08-26 09:31:30 +02:00
include NonAuthoritative zone in tests
This commit is contained in:
@@ -8,7 +8,9 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
nbdns "github.com/netbirdio/netbird/dns"
|
||||
mgmProto "github.com/netbirdio/netbird/shared/management/proto"
|
||||
)
|
||||
|
||||
func TestCreatePTRRecord_IPv4(t *testing.T) {
|
||||
@@ -136,3 +138,88 @@ func TestAddReverseZone_IPv6(t *testing.T) {
|
||||
assert.Len(t, reverseZone.Records, 1)
|
||||
assert.Equal(t, int(dns.TypePTR), reverseZone.Records[0].Type)
|
||||
}
|
||||
|
||||
// TestToDNSConfig_ZoneFlagsPreserved pins the per-zone NonAuthoritative flag
|
||||
// through the legacy DNSConfig path. A non-authoritative zone is match-only:
|
||||
// the local resolver falls through to the upstream for an in-zone name it does
|
||||
// not define. The built-in peer zone is the authoritative one and must stay
|
||||
// that way, so the flag has to travel per zone rather than be derived.
|
||||
func TestToDNSConfig_ZoneFlagsPreserved(t *testing.T) {
|
||||
config := toDNSConfig(&mgmProto.DNSConfig{
|
||||
ServiceEnable: true,
|
||||
CustomZones: []*mgmProto.CustomZone{
|
||||
{
|
||||
Domain: "netbird.cloud.",
|
||||
Records: []*mgmProto.SimpleRecord{
|
||||
{Name: "peer1.netbird.cloud.", Type: int64(dns.TypeA), Class: nbdns.DefaultClass, TTL: 300, RData: "100.64.0.1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Domain: "corp.internal.",
|
||||
NonAuthoritative: true,
|
||||
SearchDomainDisabled: true,
|
||||
Records: []*mgmProto.SimpleRecord{
|
||||
{Name: "db.corp.internal.", Type: int64(dns.TypeA), Class: nbdns.DefaultClass, TTL: 300, RData: "10.10.0.5"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, wgaddr.Address{
|
||||
IP: netip.MustParseAddr("100.64.0.1"),
|
||||
Network: netip.MustParsePrefix("100.64.0.0/16"),
|
||||
})
|
||||
|
||||
zones := make(map[string]nbdns.CustomZone, len(config.CustomZones))
|
||||
for _, zone := range config.CustomZones {
|
||||
zones[zone.Domain] = zone
|
||||
}
|
||||
|
||||
peerZone, ok := zones["netbird.cloud."]
|
||||
require.True(t, ok, "peer zone must survive")
|
||||
assert.False(t, peerZone.NonAuthoritative, "the built-in peer zone owns the account domain and stays authoritative")
|
||||
|
||||
accountZone, ok := zones["corp.internal."]
|
||||
require.True(t, ok, "account zone must survive")
|
||||
assert.True(t, accountZone.NonAuthoritative, "an account zone stays match-only, else undefined in-zone names get black-holed")
|
||||
assert.True(t, accountZone.SearchDomainDisabled)
|
||||
}
|
||||
|
||||
// TestToDNSConfig_SingleZoneForcedAuthoritative pins the compatibility clause
|
||||
// in toDNSConfig: a config carrying exactly one zone is treated as
|
||||
// authoritative no matter what the server said, because servers that predate
|
||||
// the NonAuthoritative field send only the peer FQDN zone.
|
||||
//
|
||||
// The clause can only ever downgrade an explicit true to false, so a server
|
||||
// that legitimately sends a single non-authoritative zone — an account whose
|
||||
// only zone is a custom one, with no peer records to build the built-in zone
|
||||
// from — gets that zone's whole apex black-holed on the client. Real accounts
|
||||
// always carry the peer zone alongside, which is why this is latent. Narrowing
|
||||
// it needs a way to tell "unset" from "false" on the wire, or the account
|
||||
// domain passed down here; until then this test states the contract so a
|
||||
// change to it is deliberate.
|
||||
func TestToDNSConfig_SingleZoneForcedAuthoritative(t *testing.T) {
|
||||
config := toDNSConfig(&mgmProto.DNSConfig{
|
||||
ServiceEnable: true,
|
||||
CustomZones: []*mgmProto.CustomZone{
|
||||
{
|
||||
Domain: "corp.internal.",
|
||||
NonAuthoritative: true,
|
||||
Records: []*mgmProto.SimpleRecord{
|
||||
{Name: "db.corp.internal.", Type: int64(dns.TypeA), Class: nbdns.DefaultClass, TTL: 300, RData: "10.10.0.5"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, wgaddr.Address{
|
||||
IP: netip.MustParseAddr("100.64.0.1"),
|
||||
Network: netip.MustParsePrefix("100.64.0.0/16"),
|
||||
})
|
||||
|
||||
require.NotEmpty(t, config.CustomZones)
|
||||
assert.Equal(t, "corp.internal.", config.CustomZones[0].Domain)
|
||||
assert.False(t, config.CustomZones[0].NonAuthoritative,
|
||||
"a lone zone is forced authoritative for pre-NonAuthoritative servers")
|
||||
|
||||
// The reverse zone the config gains afterwards must not feed back into the
|
||||
// decision: the compat gate counts the zones the server sent.
|
||||
require.Len(t, config.CustomZones, 2, "a reverse zone is appended for the overlay prefix")
|
||||
assert.Equal(t, "64.100.in-addr.arpa.", config.CustomZones[1].Domain)
|
||||
}
|
||||
|
||||
@@ -47,8 +47,14 @@ insert into zones (id, account_id, domain, enabled, enable_search_domain, distri
|
||||
VALUES('zone-331','account-33','test-331.com',true,true,'["33-group-one-resource-id"]');
|
||||
insert into zones (id, account_id, domain, enabled, enable_search_domain, distribution_groups)
|
||||
VALUES('zone-332','account-33','disabled-331.com',false,true,'["33-group-one-resource-id"]');
|
||||
insert into zones (id, account_id, domain, enabled, enable_search_domain, distribution_groups)
|
||||
VALUES('zone-333','account-33','search-off-331.com',true,false,'["33-group-two-resources-id"]');
|
||||
insert into records (id, account_id, zone_id, name, type, ttl, content)
|
||||
VALUES('record-333','account-33','zone-332','test.disabled-331.com','A',1800,'1.1.1.9');
|
||||
insert into records (id, account_id, zone_id, name, type, ttl, content)
|
||||
VALUES('record-334','account-33','zone-333','test.search-off-331.com','A',1800,'1.1.1.3');
|
||||
insert into records (id, account_id, zone_id, name, type, ttl, content)
|
||||
VALUES('record-335','account-33','zone-333','alias.search-off-331.com','CNAME',1800,'test.search-off-331.com');
|
||||
insert into records (id, account_id, zone_id, name, type, ttl, content)
|
||||
VALUES('record-331','account-33','zone-331','test.test-331.com','A',1800,'1.1.1.1');
|
||||
insert into records (id, account_id, zone_id, name, type, ttl, content)
|
||||
|
||||
@@ -513,6 +513,32 @@
|
||||
"SearchDomainDisabled": false,
|
||||
"NonAuthoritative": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"DistributionGroups": [
|
||||
"33-group-two-resources-id"
|
||||
],
|
||||
"Zone": {
|
||||
"Domain": "search-off-331.com.",
|
||||
"Records": [
|
||||
{
|
||||
"Name": "test.search-off-331.com.",
|
||||
"Type": 1,
|
||||
"Class": "IN",
|
||||
"TTL": 1800,
|
||||
"RData": "1.1.1.3"
|
||||
},
|
||||
{
|
||||
"Name": "alias.search-off-331.com.",
|
||||
"Type": 5,
|
||||
"Class": "IN",
|
||||
"TTL": 1800,
|
||||
"RData": "test.search-off-331.com."
|
||||
}
|
||||
],
|
||||
"SearchDomainDisabled": true,
|
||||
"NonAuthoritative": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"PrivateServiceCandidates": null,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"description": "Nameserver group and applied custom zone distributed to grp-dev; peer-a (with an extra DNS label) receives them, peer-c outside the group receives neither.",
|
||||
"description": "Nameserver group and applied custom zones distributed to grp-dev; peer-a (with an extra DNS label) receives them, peer-c is outside that group and receives only the zone distributed to grp-ops. Zone flags travel per zone: both grp-dev zones are match-only (NonAuthoritative), only search-off.internal. disables the search domain, and the built-in peer zone stays authoritative.",
|
||||
"peers": [
|
||||
"peer-a",
|
||||
"peer-c"
|
||||
|
||||
@@ -45,6 +45,27 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Domain": "search-off.internal.",
|
||||
"SearchDomainDisabled": true,
|
||||
"NonAuthoritative": true,
|
||||
"Records": [
|
||||
{
|
||||
"Name": "alias.search-off.internal.",
|
||||
"Type": "5",
|
||||
"Class": "IN",
|
||||
"TTL": "300",
|
||||
"RData": "app.search-off.internal."
|
||||
},
|
||||
{
|
||||
"Name": "app.search-off.internal.",
|
||||
"Type": "1",
|
||||
"Class": "IN",
|
||||
"TTL": "300",
|
||||
"RData": "10.10.0.6"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Domain": "netbird.test.",
|
||||
"Records": [
|
||||
|
||||
@@ -22,6 +22,19 @@
|
||||
"RData": "100.64.0.3"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Domain": "ops-only.internal.",
|
||||
"NonAuthoritative": true,
|
||||
"Records": [
|
||||
{
|
||||
"Name": "tool.ops-only.internal.",
|
||||
"Type": "1",
|
||||
"Class": "IN",
|
||||
"TTL": "300",
|
||||
"RData": "10.10.0.7"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"ForwarderPort": "22054"
|
||||
|
||||
@@ -47,6 +47,28 @@
|
||||
{"Name": "db.corp.internal.", "Type": 1, "Class": "IN", "TTL": 300, "RData": "10.10.0.5"}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"DistributionGroups": ["grp-dev"],
|
||||
"Zone": {
|
||||
"Domain": "search-off.internal.",
|
||||
"NonAuthoritative": true,
|
||||
"SearchDomainDisabled": true,
|
||||
"Records": [
|
||||
{"Name": "app.search-off.internal.", "Type": 1, "Class": "IN", "TTL": 300, "RData": "10.10.0.6"},
|
||||
{"Name": "alias.search-off.internal.", "Type": 5, "Class": "IN", "TTL": 300, "RData": "app.search-off.internal."}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"DistributionGroups": ["grp-ops"],
|
||||
"Zone": {
|
||||
"Domain": "ops-only.internal.",
|
||||
"NonAuthoritative": true,
|
||||
"Records": [
|
||||
{"Name": "tool.ops-only.internal.", "Type": 1, "Class": "IN", "TTL": 300, "RData": "10.10.0.7"}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user