improve the forbidden message

This commit is contained in:
deads2k 2016-12-13 09:17:46 -05:00
parent 9705bb728e
commit f6829bbde7
5 changed files with 37 additions and 15 deletions

View File

@ -308,7 +308,8 @@ func NewGenericServerResponse(code int, verb string, qualifiedResource schema.Gr
message = "the server has asked for the client to provide credentials"
case http.StatusForbidden:
reason = metav1.StatusReasonForbidden
message = "the server does not allow access to the requested resource"
// the server message has details about who is trying to perform what action. Keep its message.
message = serverMessage
case http.StatusMethodNotAllowed:
reason = metav1.StatusReasonMethodNotAllowed
message = "the server does not allow this method on the requested resource"

View File

@ -40,12 +40,12 @@ func WithAuthorization(handler http.Handler, requestContextMapper api.RequestCon
return
}
attrs, err := GetAuthorizerAttributes(ctx)
attributes, err := GetAuthorizerAttributes(ctx)
if err != nil {
internalError(w, req, err)
return
}
authorized, reason, err := a.Authorize(attrs)
authorized, reason, err := a.Authorize(attributes)
if authorized {
handler.ServeHTTP(w, req)
return
@ -55,8 +55,8 @@ func WithAuthorization(handler http.Handler, requestContextMapper api.RequestCon
return
}
glog.V(4).Infof("Forbidden: %#v, Reason: %s", req.RequestURI, reason)
forbidden(w, req)
glog.V(4).Infof("Forbidden: %#v, Reason: %q", req.RequestURI, reason)
forbidden(attributes, w, req, reason)
})
}

View File

@ -20,6 +20,7 @@ import (
"fmt"
"net/http"
"k8s.io/kubernetes/pkg/auth/authorizer"
"k8s.io/kubernetes/pkg/util/runtime"
)
@ -30,9 +31,28 @@ func badGatewayError(w http.ResponseWriter, req *http.Request) {
}
// forbidden renders a simple forbidden error
func forbidden(w http.ResponseWriter, req *http.Request) {
func forbidden(attributes authorizer.Attributes, w http.ResponseWriter, req *http.Request, reason string) {
msg := forbiddenMessage(attributes)
w.WriteHeader(http.StatusForbidden)
fmt.Fprintf(w, "Forbidden: %#v", req.RequestURI)
fmt.Fprintf(w, "%s: %q", msg, reason)
}
func forbiddenMessage(attributes authorizer.Attributes) string {
username := ""
if user := attributes.GetUser(); user != nil {
username = user.GetName()
}
resource := attributes.GetResource()
if group := attributes.GetAPIGroup(); len(group) > 0 {
resource = resource + "." + group
}
if ns := attributes.GetNamespace(); len(ns) > 0 {
return fmt.Sprintf("User %q cannot %s %s in the namespace %q.", username, attributes.GetVerb(), resource, ns)
}
return fmt.Sprintf("User %q cannot %s %s at the cluster scope.", username, attributes.GetVerb(), resource)
}
// internalError renders a simple internal error

View File

@ -17,6 +17,7 @@ limitations under the License.
package filters
import (
"errors"
"fmt"
"net/http"
"strings"
@ -37,7 +38,7 @@ func WithImpersonation(handler http.Handler, requestContextMapper api.RequestCon
impersonationRequests, err := buildImpersonationRequests(req.Header)
if err != nil {
glog.V(4).Infof("%v", err)
forbidden(w, req)
internalError(w, req, err)
return
}
if len(impersonationRequests) == 0 {
@ -47,12 +48,12 @@ func WithImpersonation(handler http.Handler, requestContextMapper api.RequestCon
ctx, exists := requestContextMapper.Get(req)
if !exists {
forbidden(w, req)
internalError(w, req, errors.New("no context found for request"))
return
}
requestor, exists := api.UserFrom(ctx)
if !exists {
forbidden(w, req)
internalError(w, req, errors.New("no user found for request"))
return
}
@ -100,15 +101,15 @@ func WithImpersonation(handler http.Handler, requestContextMapper api.RequestCon
userExtra[extraKey] = append(userExtra[extraKey], extraValue)
default:
glog.V(4).Infof("unknown impersonation request type: %v\n", impersonationRequest)
forbidden(w, req)
glog.V(4).Infof("unknown impersonation request type: %v", impersonationRequest)
forbidden(actingAsAttributes, w, req, fmt.Sprintf("unknown impersonation request type: %v", impersonationRequest))
return
}
allowed, reason, err := a.Authorize(actingAsAttributes)
if err != nil || !allowed {
glog.V(4).Infof("Forbidden: %#v, Reason: %s, Error: %v", req.RequestURI, reason, err)
forbidden(w, req)
forbidden(actingAsAttributes, w, req, reason)
return
}
}

View File

@ -118,7 +118,7 @@ func TestImpersonationFilter(t *testing.T) {
expectedUser: &user.DefaultInfo{
Name: "tester",
},
expectedCode: http.StatusForbidden,
expectedCode: http.StatusInternalServerError,
},
{
name: "impersonating-extra-without-user",
@ -129,7 +129,7 @@ func TestImpersonationFilter(t *testing.T) {
expectedUser: &user.DefaultInfo{
Name: "tester",
},
expectedCode: http.StatusForbidden,
expectedCode: http.StatusInternalServerError,
},
{
name: "disallowed-group",