diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/BUILD b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/BUILD index 4345c217345..071e047f9ad 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/BUILD @@ -10,13 +10,18 @@ load( go_test( name = "go_default_test", - srcs = ["status_test.go"], + srcs = [ + "errors_test.go", + "status_test.go", + ], library = ":go_default_library", tags = ["automanaged"], deps = [ "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", + "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", ], ) diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors.go index b3b964da699..5c6c9bf7561 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors.go @@ -19,22 +19,26 @@ package responsewriters import ( "fmt" "net/http" + "strings" "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apiserver/pkg/authorization/authorizer" ) +// Avoid emitting errors that look like valid HTML. Quotes are okay. +var sanitizer = strings.NewReplacer(`&`, "&", `<`, "<", `>`, ">") + // BadGatewayError renders a simple bad gateway error. func BadGatewayError(w http.ResponseWriter, req *http.Request) { w.Header().Set("Content-Type", "text/plain") w.Header().Set("X-Content-Type-Options", "nosniff") w.WriteHeader(http.StatusBadGateway) - fmt.Fprintf(w, "Bad Gateway: %#v", req.RequestURI) + fmt.Fprintf(w, "Bad Gateway: %q", sanitizer.Replace(req.RequestURI)) } // Forbidden renders a simple forbidden error func Forbidden(attributes authorizer.Attributes, w http.ResponseWriter, req *http.Request, reason string) { - msg := forbiddenMessage(attributes) + msg := sanitizer.Replace(forbiddenMessage(attributes)) w.Header().Set("Content-Type", "text/plain") w.Header().Set("X-Content-Type-Options", "nosniff") w.WriteHeader(http.StatusForbidden) @@ -76,12 +80,12 @@ func InternalError(w http.ResponseWriter, req *http.Request, err error) { w.Header().Set("Content-Type", "text/plain") w.Header().Set("X-Content-Type-Options", "nosniff") w.WriteHeader(http.StatusInternalServerError) - fmt.Fprintf(w, "Internal Server Error: %#v: %v", req.RequestURI, err) + fmt.Fprintf(w, "Internal Server Error: %q: %v", sanitizer.Replace(req.RequestURI), err) runtime.HandleError(err) } // NotFound renders a simple not found error. func NotFound(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusNotFound) - fmt.Fprintf(w, "Not Found: %#v", req.RequestURI) + fmt.Fprintf(w, "Not Found: %q", sanitizer.Replace(req.RequestURI)) } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors_test.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors_test.go new file mode 100644 index 00000000000..31f45d1e10c --- /dev/null +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors_test.go @@ -0,0 +1,84 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package responsewriters + +import ( + "errors" + "net/http" + "net/http/httptest" + "testing" + + "k8s.io/apiserver/pkg/authentication/user" + "k8s.io/apiserver/pkg/authorization/authorizer" +) + +func TestErrors(t *testing.T) { + internalError := errors.New("ARGH") + fns := map[string]func(http.ResponseWriter, *http.Request){ + "BadGatewayError": BadGatewayError, + "NotFound": NotFound, + "InternalError": func(w http.ResponseWriter, req *http.Request) { + InternalError(w, req, internalError) + }, + } + cases := []struct { + fn string + uri string + expected string + }{ + {"BadGatewayError", "/get", `Bad Gateway: "/get"`}, + {"BadGatewayError", "/