NEW FEATURE: IMPORT_TRANSFORM_STRIP (#3181)

This commit is contained in:
Tom Limoncelli 2024-10-31 15:05:56 +00:00 committed by GitHub
parent 2abbab0c84
commit 1872b12116
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 131 additions and 34 deletions

View file

@ -53,6 +53,7 @@
* [IGNORE_NAME](language-reference/domain-modifiers/IGNORE_NAME.md)
* [IGNORE_TARGET](language-reference/domain-modifiers/IGNORE_TARGET.md)
* [IMPORT_TRANSFORM](language-reference/domain-modifiers/IMPORT_TRANSFORM.md)
* [IMPORT_TRANSFORM_STRIP](language-reference/domain-modifiers/IMPORT_TRANSFORM_STRIP.md)
* [INCLUDE](language-reference/domain-modifiers/INCLUDE.md)
* [LOC](language-reference/domain-modifiers/LOC.md)
* [LOC_BUILDER_DD](language-reference/domain-modifiers/LOC_BUILDER_DD.md)

View file

@ -3,6 +3,7 @@ name: IMPORT_TRANSFORM
parameters:
- transform table
- domain
- ttl
- modifiers...
ts_ignore: true
---

View file

@ -0,0 +1,25 @@
---
name: IMPORT_TRANSFORM_STRIP
parameters:
- transform table
- domain
- ttl
- suffixstrip
- modifiers...
ts_ignore: true
---
{% hint style="warning" %}
Don't use this feature. It was added for a very specific situation at Stack Overflow.
{% endhint %}
`IMPORT_TRANSFORM_STRIP` is the same as `IMPORT_TRANSFORM` with an additional parameter: `suffixstrip`.
When `IMPORT_TRANSFORM_STRIP` is generating the label for new records, it
checks the label. If the label ends with `suffixstrip`, that suffix is removed.
If the label does not end with `suffixstrip`, an error is returned.
For example, if the domain is `com.extra` and the label is `foo.com`,
`IMPORT_TRANSFORM` would generate a label `foo.com.com.extra`.
`IMPORT_TRANSFORM_STRIP(... , '.com')` would generate
the label `foo.com.extra` instead.

View file

@ -1031,7 +1031,7 @@ function IGNORE_TARGET(target, rType) {
return IGNORE('*', rType, target);
}
// IMPORT_TRANSFORM(translation_table, domain)
// IMPORT_TRANSFORM(translation_table, domain, ttl)
var IMPORT_TRANSFORM = recordBuilder('IMPORT_TRANSFORM', {
args: [['translation_table'], ['domain'], ['ttl', _.isNumber]],
transform: function (record, args, modifiers) {
@ -1042,6 +1042,18 @@ var IMPORT_TRANSFORM = recordBuilder('IMPORT_TRANSFORM', {
},
});
// IMPORT_TRANSFORM_STRIP(translation_table, domain, ttl, suffixstrip)
var IMPORT_TRANSFORM_STRIP = recordBuilder('IMPORT_TRANSFORM', {
args: [['translation_table'], ['domain'], ['ttl', _.isNumber], ['suffixstrip']],
transform: function (record, args, modifiers) {
record.name = '@';
record.target = args.domain;
record.meta['transform_table'] = format_tt(args.translation_table);
record.ttl = args.ttl;
record.meta['transform_suffixstrip'] = args.suffixstrip;
},
});
// PURGE()
function PURGE(d) {
d.KeepUnknown = false;

30
pkg/js/parse_tests/007-importTransformTTL.js Normal file → Executable file
View file

@ -1,5 +1,25 @@
var TRANSFORM_INT = [
{low: "0.0.0.0", high: "1.1.1.1", newBase: "2.2.2.2" }
]
D("foo2.com","reg");
D("foo.com","reg",IMPORT_TRANSFORM(TRANSFORM_INT,"foo2.com",60))
var TRANSFORM_NEWIP = [{
low: "0.0.0.0",
high: "1.1.1.1",
newIP: "2.2.2.2"
}];
var TRANSFORM_BASE = [{
low: "0.0.0.0",
high: "1.1.1.1",
newBase: "4.4.4.4"
}, {
low: "7.7.7.7",
high: "8.8.8.8",
newBase: "9.9.9.9"
},
];
D("foo1.com", "reg");
D("foo2.com", "reg",
IMPORT_TRANSFORM(TRANSFORM_BASE, "foo1.com", 60)
);
D("foo3.com", "reg",
IMPORT_TRANSFORM_STRIP(TRANSFORM_NEWIP, "foo1.com", 99, ".com")
);

View file

@ -1,28 +1,45 @@
{
"registrars": [],
"dns_providers": [],
"domains": [
{
"name": "foo1.com",
"registrar": "reg",
"dnsProviders": {},
"name": "foo2.com",
"records": [],
"registrar": "reg"
"records": []
},
{
"name": "foo2.com",
"registrar": "reg",
"dnsProviders": {},
"name": "foo.com",
"records": [
{
"meta": {
"transform_table": "0.0.0.0 ~ 1.1.1.1 ~ 2.2.2.2 ~ "
},
"type": "IMPORT_TRANSFORM",
"name": "@",
"target": "foo2.com",
"ttl": 60,
"type": "IMPORT_TRANSFORM"
"meta": {
"transform_table": "0.0.0.0 ~ 1.1.1.1 ~ 4.4.4.4 ~ ; 7.7.7.7 ~ 8.8.8.8 ~ 9.9.9.9 ~ "
},
"target": "foo1.com"
}
],
"registrar": "reg"
]
},
{
"name": "foo3.com",
"registrar": "reg",
"dnsProviders": {},
"records": [
{
"type": "IMPORT_TRANSFORM",
"name": "@",
"ttl": 99,
"meta": {
"transform_suffixstrip": ".com",
"transform_table": "0.0.0.0 ~ 1.1.1.1 ~ ~ 2.2.2.2"
},
"target": "foo1.com"
}
]
}
],
"registrars": []
}
]
}

View file

@ -119,7 +119,7 @@ func checkLabel(label string, rType string, domain string, meta map[string]strin
}
if label == domain || strings.HasSuffix(label, "."+domain) {
if m := meta["skip_fqdn_check"]; m != "true" {
return fmt.Errorf(errorRepeat(label, domain))
return fmt.Errorf("%s", errorRepeat(label, domain))
}
}
@ -247,8 +247,27 @@ func transformCNAME(target, oldDomain, newDomain string) string {
return dnsutil.AddOrigin(result, newDomain) + "."
}
func newRec(rec *models.RecordConfig, ttl uint32) *models.RecordConfig {
rec2, _ := rec.Copy()
if ttl != 0 {
rec2.TTL = ttl
}
return rec2
}
func transformLabel(label, suffixstrip string) (string, error) {
if suffixstrip == "" {
return label, nil
}
if !strings.HasSuffix(label, suffixstrip) {
return "", fmt.Errorf("label %q does not end with %q", label, suffixstrip)
}
return label[:len(label)-len(suffixstrip)], nil
}
// import_transform imports the records of one zone into another, modifying records along the way.
func importTransform(srcDomain, dstDomain *models.DomainConfig, transforms []transform.IPConversion, ttl uint32) error {
func importTransform(srcDomain, dstDomain *models.DomainConfig,
transforms []transform.IPConversion, ttl uint32, suffixstrip string) error {
// Read srcDomain.Records, transform, and append to dstDomain.Records:
// 1. Skip any that aren't A or CNAMEs.
// 2. Append destDomainname to the end of the label.
@ -259,15 +278,6 @@ func importTransform(srcDomain, dstDomain *models.DomainConfig, transforms []tra
if dstDomain.Records.HasRecordTypeName(rec.Type, rec.GetLabelFQDN()) {
continue
}
newRec := func() *models.RecordConfig {
rec2, _ := rec.Copy()
newlabel := rec2.GetLabelFQDN()
rec2.SetLabel(newlabel, dstDomain.Name)
if ttl != 0 {
rec2.TTL = ttl
}
return rec2
}
switch rec.Type {
case "A":
trs, err := transform.IPToList(net.ParseIP(rec.GetTargetField()), transforms)
@ -275,12 +285,22 @@ func importTransform(srcDomain, dstDomain *models.DomainConfig, transforms []tra
return fmt.Errorf("import_transform: TransformIP(%v, %v) returned err=%s", rec.GetTargetField(), transforms, err)
}
for _, tr := range trs {
r := newRec()
r := newRec(rec, ttl)
l, err := transformLabel(r.GetLabelFQDN(), suffixstrip)
if err != nil {
return err
}
r.SetLabel(l, dstDomain.Name)
r.SetTarget(tr.String())
dstDomain.Records = append(dstDomain.Records, r)
}
case "CNAME":
r := newRec()
r := newRec(rec, ttl)
l, err := transformLabel(r.GetLabelFQDN(), suffixstrip)
if err != nil {
return err
}
r.SetLabel(l, dstDomain.Name)
r.SetTarget(transformCNAME(r.GetTargetField(), srcDomain.Name, dstDomain.Name))
dstDomain.Records = append(dstDomain.Records, r)
default:
@ -445,6 +465,7 @@ func ValidateAndNormalizeConfig(config *models.DNSConfig) (errs []error) {
for _, domain := range config.Domains {
for _, rec := range domain.Records {
if rec.Type == "IMPORT_TRANSFORM" {
suffixstrip := rec.Metadata["transform_suffixstrip"]
table, err := transform.DecodeTransformTable(rec.Metadata["transform_table"])
if err != nil {
errs = append(errs, err)
@ -455,7 +476,7 @@ func ValidateAndNormalizeConfig(config *models.DNSConfig) (errs []error) {
err = fmt.Errorf("IMPORT_TRANSFORM mentions non-existant domain %q", rec.GetTargetField())
errs = append(errs, err)
}
err = importTransform(c, domain, table, rec.TTL)
err = importTransform(c, domain, table, rec.TTL, suffixstrip)
if err != nil {
errs = append(errs, err)
}