Add Template-ability check to Kubernetes API Fields

This commit is contained in:
Daniel Tomcej 2018-10-04 02:58:03 -05:00 committed by Traefiker Bot
parent d69977c229
commit 31f92001e2
3 changed files with 79 additions and 6 deletions

View file

@ -1,6 +1,8 @@
package kubernetes
import (
"strconv"
"github.com/containous/traefik/provider/label"
)
@ -106,6 +108,13 @@ func getStringValue(annotations map[string]string, annotation string, defaultVal
return label.GetStringValue(annotations, annotationName, defaultValue)
}
func getStringSafeValue(annotations map[string]string, annotation string, defaultValue string) (string, error) {
annotationName := getAnnotationName(annotations, annotation)
value := label.GetStringValue(annotations, annotationName, defaultValue)
_, err := strconv.Unquote(`"` + value + `"`)
return value, err
}
func getBoolValue(annotations map[string]string, annotation string, defaultValue bool) bool {
annotationName := getAnnotationName(annotations, annotation)
return label.GetBoolValue(annotations, annotationName, defaultValue)

View file

@ -179,8 +179,11 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
}
for _, i := range ingresses {
annotationIngressClass := getAnnotationName(i.Annotations, annotationKubernetesIngressClass)
ingressClass := i.Annotations[annotationIngressClass]
ingressClass, err := getStringSafeValue(i.Annotations, annotationKubernetesIngressClass, "")
if err != nil {
log.Errorf("Misconfigured ingress class for ingress %s/%s: %v", i.Namespace, i.Name, err)
continue
}
if !p.shouldProcessIngress(ingressClass) {
continue
@ -221,6 +224,19 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
for _, pa := range r.HTTP.Paths {
priority := getIntValue(i.Annotations, annotationKubernetesPriority, 0)
err := templateSafeString(r.Host)
if err != nil {
log.Errorf("failed to validate host %q for ingress %s/%s: %v", r.Host, i.Namespace, i.Name, err)
continue
}
err = templateSafeString(pa.Path)
if err != nil {
log.Errorf("failed to validate path %q for ingress %s/%s: %v", pa.Path, i.Namespace, i.Name, err)
continue
}
baseName := r.Host + pa.Path
if priority > 0 {
baseName = strconv.Itoa(priority) + "-" + baseName
@ -882,15 +898,13 @@ func getFrontendRedirect(i *extensionsv1beta1.Ingress, baseName, path string) *t
}
}
redirectRegex := getStringValue(i.Annotations, annotationKubernetesRedirectRegex, "")
_, err := strconv.Unquote(`"` + redirectRegex + `"`)
redirectRegex, err := getStringSafeValue(i.Annotations, annotationKubernetesRedirectRegex, "")
if err != nil {
log.Debugf("Skipping Redirect on Ingress %s/%s due to invalid regex: %s", i.Namespace, i.Name, redirectRegex)
return nil
}
redirectReplacement := getStringValue(i.Annotations, annotationKubernetesRedirectReplacement, "")
_, err = strconv.Unquote(`"` + redirectReplacement + `"`)
redirectReplacement, err := getStringSafeValue(i.Annotations, annotationKubernetesRedirectReplacement, "")
if err != nil {
log.Debugf("Skipping Redirect on Ingress %s/%s due to invalid replacement: %q", i.Namespace, i.Name, redirectRegex)
return nil
@ -1053,3 +1067,8 @@ func getRateLimit(i *extensionsv1beta1.Ingress) *types.RateLimit {
return rateLimit
}
func templateSafeString(value string) error {
_, err := strconv.Unquote(`"` + value + `"`)
return err
}

View file

@ -3431,3 +3431,48 @@ func TestAddGlobalBackendEndpointAPIError(t *testing.T) {
err := provider.addGlobalBackend(client, ingresses, config)
assert.Error(t, err)
}
func TestTemplateBreakingIngresssValues(t *testing.T) {
ingresses := []*extensionsv1beta1.Ingress{
buildIngress(
iNamespace("testing"),
iAnnotation(annotationKubernetesIngressClass, "testing-\"foo\""),
iRules(
iRule(
iHost("foo"),
iPaths(onePath(iPath("/bar"), iBackend("service1", intstr.FromInt(80))))),
),
),
buildIngress(
iNamespace("testing"),
iRules(
iRule(
iHost("testing-\"foo\""),
iPaths(onePath(iPath("/bar"), iBackend("service1", intstr.FromInt(80))))),
),
),
buildIngress(
iNamespace("testing"),
iRules(
iRule(
iHost("foo"),
iPaths(onePath(iPath("/testing-\"foo\""), iBackend("service1", intstr.FromInt(80))))),
),
),
}
client := clientMock{
ingresses: ingresses,
}
provider := Provider{}
actual, err := provider.loadIngresses(client)
require.NoError(t, err, "error loading ingresses")
expected := buildConfiguration(
backends(),
frontends(),
)
assert.Equal(t, expected, actual)
}