mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-05 17:16:59 +02:00
fix(endpoint): domains handling with idna (#5685)
* fix(idna): fix handling of domains Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com> * fix(idna): fix handling of domains Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com> * fix(idna): fix handling of domains Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com> --------- Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
This commit is contained in:
parent
23e12c1a09
commit
0d1309c7fa
@ -25,7 +25,8 @@ import (
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/idna"
|
||||
|
||||
"sigs.k8s.io/external-dns/internal/idna"
|
||||
)
|
||||
|
||||
type MatchAllDomainFilters []DomainFilterInterface
|
||||
@ -247,9 +248,9 @@ func (df *DomainFilter) MatchParent(domain string) bool {
|
||||
}
|
||||
|
||||
// normalizeDomain converts a domain to a canonical form, so that we can filter on it
|
||||
// it: trim "." suffix, get Unicode version of domain complient with Section 5 of RFC 5891
|
||||
// it: trim "." suffix, get Unicode version of domain compliant with Section 5 of RFC 5891
|
||||
func normalizeDomain(domain string) string {
|
||||
s, err := idna.Lookup.ToUnicode(strings.TrimSuffix(domain, "."))
|
||||
s, err := idna.Profile.ToUnicode(strings.TrimSuffix(domain, "."))
|
||||
if err != nil {
|
||||
log.Warnf(`Got error while parsing domain %s: %v`, domain, err)
|
||||
}
|
||||
|
29
internal/idna/idna.go
Normal file
29
internal/idna/idna.go
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright 2025 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package idna
|
||||
|
||||
import (
|
||||
"golang.org/x/net/idna"
|
||||
)
|
||||
|
||||
var (
|
||||
Profile = idna.New(
|
||||
idna.MapForLookup(),
|
||||
idna.Transitional(true),
|
||||
idna.StrictDomainName(false),
|
||||
)
|
||||
)
|
59
internal/idna/idna_test.go
Normal file
59
internal/idna/idna_test.go
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
Copyright 2025 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package idna
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestProfileWithDefault(t *testing.T) {
|
||||
tets := []struct {
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
input: "*.GÖPHER.com",
|
||||
expected: "*.göpher.com",
|
||||
},
|
||||
{
|
||||
input: "*._abrakadabra.com",
|
||||
expected: "*._abrakadabra.com",
|
||||
},
|
||||
{
|
||||
input: "_abrakadabra.com",
|
||||
expected: "_abrakadabra.com",
|
||||
},
|
||||
{
|
||||
input: "*.foo.kube.example.com",
|
||||
expected: "*.foo.kube.example.com",
|
||||
},
|
||||
{
|
||||
input: "xn--bcher-kva.example.com",
|
||||
expected: "bücher.example.com",
|
||||
},
|
||||
}
|
||||
for _, tt := range tets {
|
||||
t.Run(strings.ToLower(tt.input), func(t *testing.T) {
|
||||
result, err := Profile.ToUnicode(tt.input)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
10
plan/plan.go
10
plan/plan.go
@ -23,9 +23,9 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/idna"
|
||||
|
||||
"sigs.k8s.io/external-dns/endpoint"
|
||||
"sigs.k8s.io/external-dns/internal/idna"
|
||||
)
|
||||
|
||||
// PropertyComparator is used in Plan for comparing the previous and current custom annotations.
|
||||
@ -340,16 +340,10 @@ func filterRecordsForPlan(records []*endpoint.Endpoint, domainFilter endpoint.Ma
|
||||
return filtered
|
||||
}
|
||||
|
||||
var idnaProfile = idna.New(
|
||||
idna.MapForLookup(),
|
||||
idna.Transitional(true),
|
||||
idna.StrictDomainName(false),
|
||||
)
|
||||
|
||||
// normalizeDNSName converts a DNS name to a canonical form, so that we can use string equality
|
||||
// it: removes space, get ASCII version of dnsName complient with Section 5 of RFC 5891, ensures there is a trailing dot
|
||||
func normalizeDNSName(dnsName string) string {
|
||||
s, err := idnaProfile.ToASCII(strings.TrimSpace(dnsName))
|
||||
s, err := idna.Profile.ToASCII(strings.TrimSpace(dnsName))
|
||||
if err != nil {
|
||||
log.Warnf(`Got error while parsing DNSName %s: %v`, dnsName, err)
|
||||
}
|
||||
|
@ -32,14 +32,16 @@ func TestZoneIDName(t *testing.T) {
|
||||
z.Add("654321", "foo.qux.baz")
|
||||
z.Add("987654", "エイミー.みんな")
|
||||
z.Add("123123", "_metadata.example.com")
|
||||
z.Add("1231231", "_foo._metadata.example.com")
|
||||
z.Add("456456", "_metadata.エイミー.みんな")
|
||||
|
||||
assert.Equal(t, ZoneIDName{
|
||||
"123456": "qux.baz",
|
||||
"654321": "foo.qux.baz",
|
||||
"987654": "エイミー.みんな",
|
||||
"123123": "_metadata.example.com",
|
||||
"456456": "_metadata.エイミー.みんな",
|
||||
"123456": "qux.baz",
|
||||
"654321": "foo.qux.baz",
|
||||
"987654": "エイミー.みんな",
|
||||
"123123": "_metadata.example.com",
|
||||
"1231231": "_foo._metadata.example.com",
|
||||
"456456": "_metadata.エイミー.みんな",
|
||||
}, z)
|
||||
|
||||
// simple entry in a domain
|
||||
@ -77,6 +79,10 @@ func TestZoneIDName(t *testing.T) {
|
||||
assert.Equal(t, "エイミー.みんな", zoneName)
|
||||
assert.Equal(t, "987654", zoneID)
|
||||
|
||||
zoneID, zoneName = z.FindZone("_foo._metadata.example.com")
|
||||
assert.Equal(t, "_foo._metadata.example.com", zoneName)
|
||||
assert.Equal(t, "1231231", zoneID)
|
||||
|
||||
hook := testutils.LogsUnderTestWithLogLevel(log.WarnLevel, t)
|
||||
_, _ = z.FindZone("???")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user