91f7a02f2c
Parameterize used strings.ReplaceAll, so an external host that merely
ends with the zone name as a substring (e.g. "notreconops.ru." against
zone "reconops.ru") was falsely rewritten to "not{{domain_name}}.".
Replace only where the zone name sits on a DNS-label boundary (start/
end of string or a non-alphanumeric/hyphen character), and resolve to
a fixed point so adjacent occurrences sharing a single boundary
character are still both replaced.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
104 lines
4.2 KiB
Go
104 lines
4.2 KiB
Go
package tmpl_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/vasyakrg/dns-autoresolver/internal/model"
|
|
"github.com/vasyakrg/dns-autoresolver/internal/store/dto"
|
|
"github.com/vasyakrg/dns-autoresolver/internal/tmpl"
|
|
)
|
|
|
|
func TestMaterializeReplacesInNameAndValues(t *testing.T) {
|
|
doc := dto.TemplateDoc{Records: []dto.RecordDTO{
|
|
{Type: "TXT", Name: "_dmarc.{{domain_name}}.", TTL: 600, Values: []string{"v=DMARC1; p=quarantine"}},
|
|
{Type: "MX", Name: "{{domain_name}}.", TTL: 600, Values: []string{"0 pmg2-mail.{{domain_name}}."}},
|
|
{Type: "TXT", Name: "{{domain_name}}.", TTL: 600, Values: []string{"v=spf1 a:mail.{{domain_name}} ~all"}},
|
|
}}
|
|
recs := tmpl.Materialize(doc, "reconops.ru.") // trailing dot stripped
|
|
if recs[0].Name != "_dmarc.reconops.ru." {
|
|
t.Fatalf("name: %q", recs[0].Name)
|
|
}
|
|
if recs[1].Values[0] != "0 pmg2-mail.reconops.ru." {
|
|
t.Fatalf("mx value: %q", recs[1].Values[0])
|
|
}
|
|
if recs[2].Values[0] != "v=spf1 a:mail.reconops.ru ~all" {
|
|
t.Fatalf("spf value: %q", recs[2].Values[0])
|
|
}
|
|
}
|
|
|
|
func TestParameterizeIsInverseForZoneOccurrences(t *testing.T) {
|
|
recs := []model.Record{
|
|
{Type: "TXT", Name: "_dmarc.reconops.ru.", TTL: 600, Values: []string{"v=DMARC1"}},
|
|
{Type: "TXT", Name: "reconops.ru.", TTL: 600, Values: []string{"v=spf1 a:mail.reconops.ru ~all"}},
|
|
{Type: "CNAME", Name: "mail.reconops.ru.", TTL: 600, Values: []string{"amail.amega.kz."}}, // external host untouched
|
|
}
|
|
doc := tmpl.Parameterize(recs, "reconops.ru.")
|
|
if doc.Records[0].Name != "_dmarc.{{domain_name}}." {
|
|
t.Fatalf("name: %q", doc.Records[0].Name)
|
|
}
|
|
if doc.Records[1].Values[0] != "v=spf1 a:mail.{{domain_name}} ~all" {
|
|
t.Fatalf("spf: %q", doc.Records[1].Values[0])
|
|
}
|
|
if doc.Records[2].Values[0] != "amail.amega.kz." {
|
|
t.Fatalf("external cname value must be untouched: %q", doc.Records[2].Values[0])
|
|
}
|
|
}
|
|
|
|
func TestParameterizeDoesNotMatchZoneNameAsSuffixOfLongerLabel(t *testing.T) {
|
|
recs := []model.Record{
|
|
{Type: "CNAME", Name: "www.reconops.ru.", TTL: 600, Values: []string{"notreconops.ru."}},
|
|
}
|
|
doc := tmpl.Parameterize(recs, "reconops.ru.")
|
|
if doc.Records[0].Values[0] != "notreconops.ru." {
|
|
t.Fatalf("external host that merely ends with the zone name must be left untouched: %q", doc.Records[0].Values[0])
|
|
}
|
|
if doc.Records[0].Name != "www.{{domain_name}}." {
|
|
t.Fatalf("name: %q", doc.Records[0].Name)
|
|
}
|
|
}
|
|
|
|
func TestParameterizeApexAndSubdomainBoundaries(t *testing.T) {
|
|
recs := []model.Record{
|
|
{Type: "A", Name: "reconops.ru.", TTL: 600, Values: []string{"1.2.3.4"}},
|
|
{Type: "TXT", Name: "_dmarc.reconops.ru.", TTL: 600, Values: []string{"v=DMARC1; p=quarantine"}},
|
|
{Type: "MX", Name: "reconops.ru.", TTL: 600, Values: []string{"0 pmg2-mail.reconops.ru."}},
|
|
}
|
|
doc := tmpl.Parameterize(recs, "reconops.ru.")
|
|
if doc.Records[0].Name != "{{domain_name}}." {
|
|
t.Fatalf("apex name: %q", doc.Records[0].Name)
|
|
}
|
|
if doc.Records[1].Name != "_dmarc.{{domain_name}}." {
|
|
t.Fatalf("sub name: %q", doc.Records[1].Name)
|
|
}
|
|
if doc.Records[2].Values[0] != "0 pmg2-mail.{{domain_name}}." {
|
|
t.Fatalf("mx value: %q", doc.Records[2].Values[0])
|
|
}
|
|
}
|
|
|
|
func TestParameterizeReplacesAllOccurrencesInSPFRecord(t *testing.T) {
|
|
recs := []model.Record{
|
|
{Type: "TXT", Name: "reconops.ru.", TTL: 600, Values: []string{"v=spf1 a:mail.reconops.ru a:pmg2-mail.reconops.ru ~all"}},
|
|
}
|
|
doc := tmpl.Parameterize(recs, "reconops.ru.")
|
|
want := "v=spf1 a:mail.{{domain_name}} a:pmg2-mail.{{domain_name}} ~all"
|
|
if doc.Records[0].Values[0] != want {
|
|
t.Fatalf("spf: got %q, want %q", doc.Records[0].Values[0], want)
|
|
}
|
|
}
|
|
|
|
func TestParameterizeReplacesAdjacentZoneOccurrencesSharingASingleBoundary(t *testing.T) {
|
|
// Two zone-name occurrences separated by exactly one boundary character
|
|
// (the dot). A single non-overlapping regexp pass would only catch the
|
|
// first occurrence, since the shared "." is consumed as its right
|
|
// boundary and is then unavailable as the second occurrence's left
|
|
// boundary. replaceZoneBoundary must still resolve both.
|
|
recs := []model.Record{
|
|
{Type: "TXT", Name: "reconops.ru.", TTL: 600, Values: []string{"reconops.ru.reconops.ru."}},
|
|
}
|
|
doc := tmpl.Parameterize(recs, "reconops.ru.")
|
|
want := "{{domain_name}}.{{domain_name}}."
|
|
if doc.Records[0].Values[0] != want {
|
|
t.Fatalf("adjacent occurrences: got %q, want %q", doc.Records[0].Values[0], want)
|
|
}
|
|
}
|