From d0d7f4c89abebcfb5783fcf1ea4fe1a2090e9f11 Mon Sep 17 00:00:00 2001 From: Markus Sommer Date: Fri, 4 Aug 2017 15:41:55 +0200 Subject: [PATCH] Kubernetes srv (#823) * Treat absence of port/service in SRV as wildcard Normally, a SRV-request should have the form _._... The k8s peer-finder which is used for bootstrapping by some applications will however query for SRV at .. To compensate for this behaviour, treat the absence of _ and _ as wildcards. * Modified tests with new SRV behaviour Added a testcase for a SRV request without port & service Removed now valid query from invalidSRVQueries * Forgot to run gofmt on test/kubernetes_test.go --- middleware/kubernetes/kubernetes.go | 52 ++++++++++++++---------- middleware/kubernetes/kubernetes_test.go | 1 - test/kubernetes_test.go | 7 +++- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/middleware/kubernetes/kubernetes.go b/middleware/kubernetes/kubernetes.go index 8a87322e8..7d824f890 100644 --- a/middleware/kubernetes/kubernetes.go +++ b/middleware/kubernetes/kubernetes.go @@ -299,34 +299,42 @@ func (k *Kubernetes) parseRequest(lowerCasedName string, qtype uint16) (r record offset := 0 if qtype == dns.TypeSRV { - if len(segs) != 5 { - return r, errInvalidRequest - } - // This is a SRV style request, get first two elements as port and - // protocol, stripping leading underscores if present. - if segs[0][0] == '_' { - r.port = segs[0][1:] + // The kubernetes peer-finder expects queries with empty port and service to resolve + // If neither is specified, treat it as a wildcard + if len(segs) == 3 { + r.port = "*" + r.service = "*" + offset = 0 } else { - r.port = segs[0] - if !symbolContainsWildcard(r.port) { + if len(segs) != 5 { return r, errInvalidRequest } - } - if segs[1][0] == '_' { - r.protocol = segs[1][1:] - if r.protocol != "tcp" && r.protocol != "udp" { - return r, errInvalidRequest - } - } else { - r.protocol = segs[1] - if !symbolContainsWildcard(r.protocol) { + // This is a SRV style request, get first two elements as port and + // protocol, stripping leading underscores if present. + if segs[0][0] == '_' { + r.port = segs[0][1:] + } else { + r.port = segs[0] + if !symbolContainsWildcard(r.port) { + return r, errInvalidRequest + } + } + if segs[1][0] == '_' { + r.protocol = segs[1][1:] + if r.protocol != "tcp" && r.protocol != "udp" { + return r, errInvalidRequest + } + } else { + r.protocol = segs[1] + if !symbolContainsWildcard(r.protocol) { + return r, errInvalidRequest + } + } + if r.port == "" || r.protocol == "" { return r, errInvalidRequest } + offset = 2 } - if r.port == "" || r.protocol == "" { - return r, errInvalidRequest - } - offset = 2 } if (qtype == dns.TypeA || qtype == dns.TypeAAAA) && len(segs) == 4 { // This is an endpoint A/AAAA record request. Get first element as endpoint. diff --git a/middleware/kubernetes/kubernetes_test.go b/middleware/kubernetes/kubernetes_test.go index c93270cbe..94a3c94ac 100644 --- a/middleware/kubernetes/kubernetes_test.go +++ b/middleware/kubernetes/kubernetes_test.go @@ -227,7 +227,6 @@ func TestParseRequest(t *testing.T) { } invalidSRVQueries := []string{ - "webs.mynamespace.svc.inter.webs.test.", // SRV requests must have port and protocol "_http._pcp.webs.mynamespace.svc.inter.webs.test.", // SRV protocol must be tcp or udp "_http._tcp.ep.webs.ns.svc.inter.webs.test.", // SRV requests cannot have an endpoint "_*._*.webs.mynamespace.svc.inter.webs.test.", // SRV request with invalid wildcards diff --git a/test/kubernetes_test.go b/test/kubernetes_test.go index c0c836911..ac5414743 100644 --- a/test/kubernetes_test.go +++ b/test/kubernetes_test.go @@ -207,8 +207,11 @@ var dnsTestCases = []test.Case{ }, { Qname: "svc-1-a.test-1.svc.cluster.local.", Qtype: dns.TypeSRV, - Rcode: dns.RcodeNameError, - Answer: []dns.RR{}, + Rcode: dns.RcodeSuccess, + Answer: []dns.RR{ + test.SRV("_http._tcp.svc-1-a.test-1.svc.cluster.local. 303 IN SRV 10 100 80 svc-1-a.test-1.svc.cluster.local."), + test.SRV("_https._tcp.svc-1-a.test-1.svc.cluster.local. 303 IN SRV 10 100 443 svc-1-a.test-1.svc.cluster.local."), + }, }, { Qname: "10-20-0-101.test-1.pod.cluster.local.", Qtype: dns.TypeA,