From f0483b152fbc8b98e15bc790b36dbfa962e61eb4 Mon Sep 17 00:00:00 2001 From: Mustafa Abdelrahman Date: Mon, 6 Nov 2023 19:20:41 +0100 Subject: [PATCH] Validate that network backends doesn't have paths Signed-off-by: Mustafa Abdelrahman --- .../definitions/routegroupvalidator.go | 15 +++++ .../testdata/errorwrapdata/errors.log | 4 ++ .../testdata/errorwrapdata/routegroups.json | 56 +++++++++++++++++++ .../route-with-invalid-backend-with-path.log | 1 + .../route-with-invalid-backend-with-path.yaml | 41 ++++++++++++++ .../route-with-multiple-filters-one-item.log | 2 +- 6 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 dataclients/kubernetes/definitions/testdata/validation/route-with-invalid-backend-with-path.log create mode 100644 dataclients/kubernetes/definitions/testdata/validation/route-with-invalid-backend-with-path.yaml diff --git a/dataclients/kubernetes/definitions/routegroupvalidator.go b/dataclients/kubernetes/definitions/routegroupvalidator.go index 4911f7910c..bb3d3fe72c 100644 --- a/dataclients/kubernetes/definitions/routegroupvalidator.go +++ b/dataclients/kubernetes/definitions/routegroupvalidator.go @@ -3,6 +3,7 @@ package definitions import ( "errors" "fmt" + "net/url" "github.com/zalando/skipper/eskip" ) @@ -37,6 +38,7 @@ func (rgv *RouteGroupValidator) Validate(item *RouteGroupItem) error { var errs []error errs = append(errs, rgv.filtersValidation(item)) errs = append(errs, rgv.predicatesValidation(item)) + errs = append(errs, rgv.validateBackends(item)) return errorsJoin(errs...) } @@ -91,6 +93,19 @@ func (rgv *RouteGroupValidator) predicatesValidation(item *RouteGroupItem) error return errorsJoin(errs...) } +func (rgv *RouteGroupValidator) validateBackends(item *RouteGroupItem) error { + var errs []error + for _, backend := range item.Spec.Backends { + address, err := url.Parse(backend.Address) + if err != nil { + errs = append(errs, fmt.Errorf("failed to parse backend address %s: %w", backend.Address, err)) + } else if address.Path != "" { + errs = append(errs, fmt.Errorf("backend address %s contains path", backend.Address)) + } + } + return errorsJoin(errs...) +} + // TODO: we need to pass namespace/name in all errors func (rg *RouteGroupSpec) validate() error { // has at least one backend: diff --git a/dataclients/kubernetes/definitions/testdata/errorwrapdata/errors.log b/dataclients/kubernetes/definitions/testdata/errorwrapdata/errors.log index 836138e99f..889bcb07f8 100644 --- a/dataclients/kubernetes/definitions/testdata/errorwrapdata/errors.log +++ b/dataclients/kubernetes/definitions/testdata/errorwrapdata/errors.log @@ -4,3 +4,7 @@ single predicate expected at "Path(\"/foo\") && Method(\"GET\")" single predicate expected at "" single filter expected at "inlineContent(\"/foo\") -> status(200)" single filter expected at " " +backend address "http://example.com/foo" contains path +backend address "http://example.com/foo/bar" contains path +backend address "http://example.com/foo/" contains path +backend address "/foo" contains path diff --git a/dataclients/kubernetes/definitions/testdata/errorwrapdata/routegroups.json b/dataclients/kubernetes/definitions/testdata/errorwrapdata/routegroups.json index 270d491ec9..68436db467 100644 --- a/dataclients/kubernetes/definitions/testdata/errorwrapdata/routegroups.json +++ b/dataclients/kubernetes/definitions/testdata/errorwrapdata/routegroups.json @@ -134,6 +134,62 @@ } ] } + }, + { + "apiVersion": "zalando.org/v1", + "metadata": { + "name": "rg1" + }, + "kind": "RouteGroup", + "spec": { + "backends": [ + { + "name": "backend1", + "type": "network", + "address": "http://example.com" + }, + { + "name": "backend2", + "type": "network", + "address": "http://example.com/foo" + }, + { + "name": "backend3", + "type": "network", + "address": "http://example.com/foo/bar" + }, + { + "name": "backend4", + "type": "network", + "address": "http://example.com/foo/" + }, + { + "name": "backend5", + "type": "network", + "address": "/foo" + }, + { + "name": "shunt", + "type": "shunt" + } + ], + "hosts": [ + "test.example.com" + ], + "routes": [ + { + "backends": [ + { + "backendName": "shunt" + } + ], + "filters": [ + "inlineContent(\"/foo\")" + ], + "path": "/foo" + } + ] + } } ] } diff --git a/dataclients/kubernetes/definitions/testdata/validation/route-with-invalid-backend-with-path.log b/dataclients/kubernetes/definitions/testdata/validation/route-with-invalid-backend-with-path.log new file mode 100644 index 0000000000..442e2e4bbf --- /dev/null +++ b/dataclients/kubernetes/definitions/testdata/validation/route-with-invalid-backend-with-path.log @@ -0,0 +1 @@ +backend address \"http://example.com/foo\" contains path\nbackend address \"http://example.com/foo/bar\" contains path\nbackend address \"/foo\" contains path\nbackend address \"/foo/bar\" contains path \ No newline at end of file diff --git a/dataclients/kubernetes/definitions/testdata/validation/route-with-invalid-backend-with-path.yaml b/dataclients/kubernetes/definitions/testdata/validation/route-with-invalid-backend-with-path.yaml new file mode 100644 index 0000000000..d09f0ac319 --- /dev/null +++ b/dataclients/kubernetes/definitions/testdata/validation/route-with-invalid-backend-with-path.yaml @@ -0,0 +1,41 @@ +apiVersion: zalando.org/v1 +kind: RouteGroup +metadata: + name: test-route-group +spec: + hosts: + - example.org + backends: + - name: app + type: service + serviceName: app-svc + servicePort: 80 + - name: backend1 + type: network + address: http://example.com + - name: backend2 + type: network + address: http://example.com/foo + - name: backend3 + type: network + address: http://example.com/foo/bar + - name: backend4 + type: network + address: /foo + - name: backend5 + type: network + address: /foo/bar + defaultBackends: + - backendName: app + routes: + - path: / + methods: + - GET + - HEAD + predicates: + - Foo("X-Bar", "42") + filters: + - foo(42) + - bar(24) + backends: + - backendName: app diff --git a/dataclients/kubernetes/definitions/testdata/validation/route-with-multiple-filters-one-item.log b/dataclients/kubernetes/definitions/testdata/validation/route-with-multiple-filters-one-item.log index 6300163089..e2640cbb65 100644 --- a/dataclients/kubernetes/definitions/testdata/validation/route-with-multiple-filters-one-item.log +++ b/dataclients/kubernetes/definitions/testdata/validation/route-with-multiple-filters-one-item.log @@ -1 +1 @@ -single filter expected +single filter expected at "foo(42) -> bar(24)" \ No newline at end of file