diff --git a/discovery/kubernetes/ingress.go b/discovery/kubernetes/ingress.go index 63d86c3b1..0b27c116b 100644 --- a/discovery/kubernetes/ingress.go +++ b/discovery/kubernetes/ingress.go @@ -15,6 +15,7 @@ package kubernetes import ( "context" + "strings" "github.com/go-kit/log" "github.com/go-kit/log/level" @@ -193,18 +194,16 @@ func (i *Ingress) buildIngress(ingress ingressAdaptor) *targetgroup.Group { } tg.Labels = ingressLabels(ingress) - tlsHosts := make(map[string]struct{}) - for _, host := range ingress.tlsHosts() { - tlsHosts[host] = struct{}{} - } - for _, rule := range ingress.rules() { + scheme := "http" paths := pathsFromIngressPaths(rule.paths()) - scheme := "http" - _, isTLS := tlsHosts[rule.host()] - if isTLS { - scheme = "https" + out: + for _, pattern := range ingress.tlsHosts() { + if matchesHostnamePattern(pattern, rule.host()) { + scheme = "https" + break out + } } for _, path := range paths { @@ -219,3 +218,34 @@ func (i *Ingress) buildIngress(ingress ingressAdaptor) *targetgroup.Group { return tg } + +// matchesHostnamePattern returns true if the host matches a wildcard DNS +// pattern or pattern and host are equal +func matchesHostnamePattern(pattern, host string) bool { + // check for exact match + if pattern == host { + return true + } + + patternParts := strings.Split(pattern, ".") + hostParts := strings.Split(host, ".") + + // if they are not equal, we cna check if we need to match + // on a wildcard or else give up + if len(patternParts) == 0 || patternParts[0] != "*" { + return false + } + + // to get a valid wildcard match the parts will need to be the same length + if len(patternParts) != len(hostParts) { + return false + } + + for i := 1; i < len(patternParts); i++ { + if patternParts[i] != hostParts[i] { + return false + } + } + + return true +} diff --git a/discovery/kubernetes/ingress_test.go b/discovery/kubernetes/ingress_test.go index 5e383a480..a8e6a41ad 100644 --- a/discovery/kubernetes/ingress_test.go +++ b/discovery/kubernetes/ingress_test.go @@ -19,11 +19,11 @@ import ( "testing" "github.com/prometheus/common/model" + "github.com/prometheus/prometheus/discovery/targetgroup" + v1 "k8s.io/api/networking/v1" "k8s.io/api/networking/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/prometheus/prometheus/discovery/targetgroup" ) type TLSMode int @@ -32,6 +32,7 @@ const ( TLSNo TLSMode = iota TLSYes TLSMixed + TLSWildcard ) func makeIngress(tls TLSMode) *v1.Ingress { @@ -81,6 +82,8 @@ func makeIngress(tls TLSMode) *v1.Ingress { ret.Spec.TLS = []v1.IngressTLS{{Hosts: []string{"example.com", "test.example.com"}}} case TLSMixed: ret.Spec.TLS = []v1.IngressTLS{{Hosts: []string{"example.com"}}} + case TLSWildcard: + ret.Spec.TLS = []v1.IngressTLS{{Hosts: []string{"*.example.com"}}} } return ret @@ -133,6 +136,8 @@ func makeIngressV1beta1(tls TLSMode) *v1beta1.Ingress { ret.Spec.TLS = []v1beta1.IngressTLS{{Hosts: []string{"example.com", "test.example.com"}}} case TLSMixed: ret.Spec.TLS = []v1beta1.IngressTLS{{Hosts: []string{"example.com"}}} + case TLSWildcard: + ret.Spec.TLS = []v1beta1.IngressTLS{{Hosts: []string{"*.example.com"}}} } return ret @@ -152,6 +157,8 @@ func expectedTargetGroups(ns string, tls TLSMode) map[string]*targetgroup.Group scheme2 = "https" case TLSMixed: scheme1 = "https" + case TLSWildcard: + scheme2 = "https" } key := fmt.Sprintf("ingress/%s/testingress", ns)