Add Template-ability check to Kubernetes API Fields
This commit is contained in:
parent
d69977c229
commit
31f92001e2
3 changed files with 79 additions and 6 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue