From c96a22dd7ff446e8eb335b83ab939064f79bd9c1 Mon Sep 17 00:00:00 2001 From: David Dansby <39511285+DataDavD@users.noreply.github.com> Date: Thu, 19 Aug 2021 01:47:33 -0700 Subject: [PATCH] Create InvalidAPIEndpointHandler to be chi-Mount'd on BaseURL This commit works to close issue #2190 by creating handler that returns ErrInvalidAPIEndpoint when called. This will be used by chi Mount'ing the handler to a specified route so that any calls to a route downstream the Mount'd pattern will respond with the ErrInvalidAPIEndpoint error. Also add corresponding test, TestInvalidRoute, to test InvalidAPIEndpointHandler. Create middleware to catch downstream routes from BaseURL This commit works to close issue #2190 by creating middleware to ensure users that call routes downstream of the BaseURL (i.e. /api/v1) are return an invalid endpoint error and internal error status. Remove BaseURLHandler --- pkg/api/serve.go | 10 ++++++++++ pkg/api/serve_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/pkg/api/serve.go b/pkg/api/serve.go index 5bc7ffed954..c93ffea55db 100644 --- a/pkg/api/serve.go +++ b/pkg/api/serve.go @@ -33,6 +33,8 @@ const ( extensionValidationExcludeBody = "x-validation-exclude-body" ) +var ErrInvalidAPIEndpoint = errors.New("invalid API endpoint") + type responseError struct { Message string `json:"message"` } @@ -85,6 +87,7 @@ func Serve( r.Mount("/_pprof/", httputil.ServePPROF("/_pprof/")) r.Mount("/swagger.json", http.HandlerFunc(swaggerSpecHandler)) r.Mount("/", uiHandler) + r.Mount(BaseURL, http.HandlerFunc(InvalidAPIEndpointHandler)) return r } @@ -162,3 +165,10 @@ func validateRequest(r *http.Request, router routers.Router, options *openapi3fi } return http.StatusOK, nil } + +// InvalidAPIEndpointHandler returns ErrInvalidAPIEndpoint, and is currently being used to ensure +// that routes under the pattern it is used with in chi.Router.Mount (i.e. /api/v1) are +// not accessible. +func InvalidAPIEndpointHandler(w http.ResponseWriter, _ *http.Request) { + writeError(w, http.StatusInternalServerError, ErrInvalidAPIEndpoint) +} diff --git a/pkg/api/serve_test.go b/pkg/api/serve_test.go index ebd02b20b16..2ae91d5a3c2 100644 --- a/pkg/api/serve_test.go +++ b/pkg/api/serve_test.go @@ -178,3 +178,34 @@ func setupClientWithAdmin(t testing.TB, blockstoreType string, opts ...testutil. clt = setupClientByEndpoint(t, server.URL, cred.AccessKeyID, cred.SecretAccessKey) return clt, deps } + +func TestInvalidRoute(t *testing.T) { + handler, _ := setupHandler(t, "") + server := setupServer(t, handler) + clt := setupClientByEndpoint(t, server.URL, "", "") + cred := createDefaultAdminUser(t, clt) + + // setup client with invalid endpoint base url + basicAuthProvider, err := securityprovider.NewSecurityProviderBasicAuth(cred.AccessKeyID, cred.SecretAccessKey) + if err != nil { + t.Fatal("basic auth security provider", err) + } + clt, err = api.NewClientWithResponses(server.URL+api.BaseURL+"//", api.WithRequestEditorFn(basicAuthProvider.Intercept)) + if err != nil { + t.Fatal("failed to create api client:", err) + } + + ctx := context.Background() + resp, err := clt.ListRepositoriesWithResponse(ctx, &api.ListRepositoriesParams{}) + if err != nil { + t.Fatalf("failed to get lakefs server version") + } + if resp.JSONDefault == nil { + t.Fatalf("client api call expected default error, got nil") + } + expectedErrMsg := api.ErrInvalidAPIEndpoint.Error() + errMsg := resp.JSONDefault.Message + if errMsg != expectedErrMsg { + t.Fatalf("client response error message: %s, expected: %s", errMsg, expectedErrMsg) + } +}