Skip to content

Commit

Permalink
add support for root-level records
Browse files Browse the repository at this point in the history
closes #1171
  • Loading branch information
BeryJu committed Oct 11, 2024
1 parent 5ab1732 commit 5386356
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 1 deletion.
2 changes: 2 additions & 0 deletions docs/content/docs/dns/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ Each zone has its individual configuration for how to handle queries, see [Handl

A record belongs to one zone and stores one response. To support multiple responses (i.e. multiple IP addresses for an A record), record UIDs are used. A UID is optional, and records with UID can be combined with a record without UID (all their results will be returned). Records created by the DHCP role will automatically have the UID assigned based on the DHCP device's identifier (the MAC address in most cases).

To create a record at the root of the zone, set the name of the record to `@`.

A single record holds the following data:

- `data`: The actual response, an IP for A/AAAA records, text for TXT records, etc.
Expand Down
11 changes: 10 additions & 1 deletion pkg/roles/dns/handler_etcd.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,16 @@ func (eh *EtcdHandler) findWildcard(r *utils.DNSRequest, relRecordName string, q

func (eh *EtcdHandler) handleSingleQuestion(question dns.Question, r *utils.DNSRequest) []dns.RR {
answers := []dns.RR{}
relRecordName := strings.TrimSuffix(strings.ToLower(question.Name), strings.ToLower(utils.EnsureLeadingPeriod(eh.z.Name)))
// Remove zone from query name
relRecordName := strings.TrimSuffix(strings.ToLower(question.Name), strings.ToLower(eh.z.Name))
if relRecordName == "" {
// If the query name was the zone, the query should look for a record at the root
relRecordName = types.DNSRoot
} else {
// Otherwise the relative record name still has a dot at the end which is not what we store
// in the database
relRecordName = strings.TrimSuffix(relRecordName, ".")
}
directRecordKey := eh.z.inst.KV().Key(
eh.z.etcdKey,
strings.ToLower(relRecordName),
Expand Down
57 changes: 57 additions & 0 deletions pkg/roles/dns/handler_etcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"github.com/stretchr/testify/assert"
)

const TestZone = "example.com."

func TestRoleDNS_Etcd(t *testing.T) {
defer tests.Setup(t)()
rootInst := instance.New()
Expand Down Expand Up @@ -66,6 +68,61 @@ func TestRoleDNS_Etcd(t *testing.T) {
assert.Equal(t, net.ParseIP("10.1.2.3").String(), ans.(*d.A).A.String())
}

// Test DNS Entry at root of zone
func TestRoleDNS_Etcd_Root(t *testing.T) {
defer tests.Setup(t)()
rootInst := instance.New()
ctx := tests.Context()
inst := rootInst.ForRole("dns", ctx)
tests.PanicIfError(inst.KV().Put(
ctx,
inst.KV().Key(
types.KeyRole,
types.KeyZones,
TestZone,
).String(),
tests.MustJSON(dns.Zone{
HandlerConfigs: []map[string]string{
{
"type": "etcd",
},
},
}),
))
tests.PanicIfError(inst.KV().Put(
ctx,
inst.KV().Key(
types.KeyRole,
types.KeyZones,
TestZone,
"@",
types.DNSRecordTypeA,
"0",
).String(),
tests.MustJSON(dns.Record{
Data: "10.1.2.3",
}),
))

role := dns.New(inst)
assert.NotNil(t, role)
assert.Nil(t, role.Start(ctx, RoleConfig()))
defer role.Stop()

fw := NewNullDNSWriter()
role.Handler(fw, &d.Msg{
Question: []d.Question{
{
Name: TestZone,
Qtype: d.TypeA,
Qclass: d.ClassINET,
},
},
})
ans := fw.Msg().Answer[0]
assert.Equal(t, net.ParseIP("10.1.2.3").String(), ans.(*d.A).A.String())
}

func TestRoleDNS_Etcd_Wildcard(t *testing.T) {
defer tests.Setup(t)()
rootInst := instance.New()
Expand Down
1 change: 1 addition & 0 deletions pkg/roles/dns/types/role.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const (

const (
DNSWildcard = "*"
DNSRoot = "@"
)

const (
Expand Down

0 comments on commit 5386356

Please sign in to comment.