// TestAdminDebugRedirect verifies that the /debug/ endpoint is redirected to on // incorrect /debug/ paths. func TestAdminDebugRedirect(t *testing.T) { defer leaktest.AfterTest(t)() s, _, _ := serverutils.StartServer(t, base.TestServerArgs{}) defer s.Stopper().Stop() expURL := debugURL(s) origURL := expURL + "incorrect" // There are no particular permissions on admin endpoints, TestUser is fine. client, err := testutils.NewTestBaseContext(TestUser).GetHTTPClient() if err != nil { t.Fatal(err) } // Don't follow redirects automatically. redirectAttemptedError := errors.New("redirect") client.CheckRedirect = func(req *http.Request, via []*http.Request) error { return redirectAttemptedError } resp, err := client.Get(origURL) if urlError, ok := err.(*url.Error); ok && urlError.Err == redirectAttemptedError { // Ignore the redirectAttemptedError. err = nil } if err != nil { t.Fatal(err) } else { resp.Body.Close() if resp.StatusCode != http.StatusMovedPermanently { t.Errorf("expected status code %d; got %d", http.StatusMovedPermanently, resp.StatusCode) } if redirectURL, err := resp.Location(); err != nil { t.Error(err) } else if foundURL := redirectURL.String(); foundURL != expURL { t.Errorf("expected location %s; got %s", expURL, foundURL) } } }
// Verify client certificate enforcement and user whitelisting. func TestSSLEnforcement(t *testing.T) { defer leaktest.AfterTest(t)() s, _, _ := serverutils.StartServer(t, base.TestServerArgs{}) defer s.Stopper().Stop() // HTTPS with client certs for security.RootUser. rootCertsContext := testutils.NewTestBaseContext(security.RootUser) // HTTPS with client certs for security.NodeUser. nodeCertsContext := testutils.NewNodeTestBaseContext() // HTTPS with client certs for TestUser. testCertsContext := testutils.NewTestBaseContext(TestUser) // HTTPS without client certs. The user does not matter. noCertsContext := insecureCtx{} // Plain http. insecureContext := testutils.NewTestBaseContext(TestUser) insecureContext.Insecure = true kvGet := &roachpb.GetRequest{} kvGet.Key = roachpb.Key("/") testCases := []struct { method, path string body proto.Message ctx ctxI success bool // request sent successfully (may be non-200) code int // http response code }{ // /ui/: basic file server: no auth. {"GET", "/index.html", nil, rootCertsContext, true, http.StatusOK}, {"GET", "/index.html", nil, nodeCertsContext, true, http.StatusOK}, {"GET", "/index.html", nil, testCertsContext, true, http.StatusOK}, {"GET", "/index.html", nil, noCertsContext, true, http.StatusOK}, {"GET", "/index.html", nil, insecureContext, true, http.StatusPermanentRedirect}, // /_admin/: server.adminServer: no auth. {"GET", adminPrefix + "health", nil, rootCertsContext, true, http.StatusOK}, {"GET", adminPrefix + "health", nil, nodeCertsContext, true, http.StatusOK}, {"GET", adminPrefix + "health", nil, testCertsContext, true, http.StatusOK}, {"GET", adminPrefix + "health", nil, noCertsContext, true, http.StatusOK}, {"GET", adminPrefix + "health", nil, insecureContext, true, http.StatusPermanentRedirect}, // /debug/: server.adminServer: no auth. {"GET", debugEndpoint + "vars", nil, rootCertsContext, true, http.StatusOK}, {"GET", debugEndpoint + "vars", nil, nodeCertsContext, true, http.StatusOK}, {"GET", debugEndpoint + "vars", nil, testCertsContext, true, http.StatusOK}, {"GET", debugEndpoint + "vars", nil, noCertsContext, true, http.StatusOK}, {"GET", debugEndpoint + "vars", nil, insecureContext, true, http.StatusPermanentRedirect}, // /_status/nodes: server.statusServer: no auth. {"GET", statusPrefix + "nodes", nil, rootCertsContext, true, http.StatusOK}, {"GET", statusPrefix + "nodes", nil, nodeCertsContext, true, http.StatusOK}, {"GET", statusPrefix + "nodes", nil, testCertsContext, true, http.StatusOK}, {"GET", statusPrefix + "nodes", nil, noCertsContext, true, http.StatusOK}, {"GET", statusPrefix + "nodes", nil, insecureContext, true, http.StatusPermanentRedirect}, // /ts/: ts.Server: no auth. {"GET", ts.URLPrefix, nil, rootCertsContext, true, http.StatusNotFound}, {"GET", ts.URLPrefix, nil, nodeCertsContext, true, http.StatusNotFound}, {"GET", ts.URLPrefix, nil, testCertsContext, true, http.StatusNotFound}, {"GET", ts.URLPrefix, nil, noCertsContext, true, http.StatusNotFound}, {"GET", ts.URLPrefix, nil, insecureContext, true, http.StatusPermanentRedirect}, } for tcNum, tc := range testCases { client, err := tc.ctx.GetHTTPClient() if err != nil { t.Fatalf("[%d]: failed to get http client: %v", tcNum, err) } url := fmt.Sprintf( "%s://%s%s", tc.ctx.HTTPRequestScheme(), s.(*TestServer).Cfg.HTTPAddr, tc.path) resp, err := doHTTPReq(t, client, tc.method, url, tc.body) if (err == nil) != tc.success { t.Errorf("[%d]: expected success=%t, got err=%v", tcNum, tc.success, err) } if err != nil { continue } defer resp.Body.Close() if resp.StatusCode != tc.code { t.Errorf("[%d]: expected status code %d, got %d", tcNum, tc.code, resp.StatusCode) } } }