diff --git a/pkg/apiserver/api_installer.go b/pkg/apiserver/api_installer.go index 2c52c4ce3a7..643c20ec09a 100644 --- a/pkg/apiserver/api_installer.go +++ b/pkg/apiserver/api_installer.go @@ -752,7 +752,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag default: return nil, fmt.Errorf("unrecognized action verb: %s", action.Verb) } - // Note: update GetAttribs() when adding a custom handler. + // Note: update GetAuthorizerAttributes() when adding a custom handler. } return &apiResource, nil } diff --git a/pkg/apiserver/filters/audit.go b/pkg/apiserver/filters/audit.go index 46546a41724..852940d102c 100644 --- a/pkg/apiserver/filters/audit.go +++ b/pkg/apiserver/filters/audit.go @@ -18,6 +18,7 @@ package filters import ( "bufio" + "errors" "fmt" "io" "net" @@ -28,6 +29,7 @@ import ( "github.com/golang/glog" "github.com/pborman/uuid" + "k8s.io/kubernetes/pkg/api" authenticationapi "k8s.io/kubernetes/pkg/apis/authentication" utilnet "k8s.io/kubernetes/pkg/util/net" ) @@ -86,12 +88,17 @@ var _ http.Hijacker = &fancyResponseWriterDelegator{} // 2. the response line containing: // - the unique id from 1 // - response code -func WithAudit(handler http.Handler, attributeGetter RequestAttributeGetter, out io.Writer) http.Handler { +func WithAudit(handler http.Handler, requestContextMapper api.RequestContextMapper, out io.Writer) http.Handler { if out == nil { return handler } return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - attribs, err := attributeGetter.GetAttribs(req) + ctx, ok := requestContextMapper.Get(req) + if !ok { + internalError(w, req, errors.New("no context found for request")) + return + } + attribs, err := GetAuthorizerAttributes(ctx) if err != nil { internalError(w, req, err) return diff --git a/pkg/apiserver/filters/audit_test.go b/pkg/apiserver/filters/audit_test.go index 69e19d99546..327a2ab44ef 100644 --- a/pkg/apiserver/filters/audit_test.go +++ b/pkg/apiserver/filters/audit_test.go @@ -74,10 +74,9 @@ func (*fakeHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { func TestAudit(t *testing.T) { var buf bytes.Buffer - attributeGetter := NewRequestAttributeGetter(&fakeRequestContextMapper{ + handler := WithAudit(&fakeHTTPHandler{}, &fakeRequestContextMapper{ user: &user.DefaultInfo{Name: "admin"}, - }) - handler := WithAudit(&fakeHTTPHandler{}, attributeGetter, &buf) + }, &buf) req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil) req.RemoteAddr = "127.0.0.1" diff --git a/pkg/apiserver/filters/authorization.go b/pkg/apiserver/filters/authorization.go index 74567cd6246..6ac4d08673e 100644 --- a/pkg/apiserver/filters/authorization.go +++ b/pkg/apiserver/filters/authorization.go @@ -28,13 +28,19 @@ import ( ) // WithAuthorizationCheck passes all authorized requests on to handler, and returns a forbidden error otherwise. -func WithAuthorization(handler http.Handler, getAttribs RequestAttributeGetter, a authorizer.Authorizer) http.Handler { +func WithAuthorization(handler http.Handler, requestContextMapper api.RequestContextMapper, a authorizer.Authorizer) http.Handler { if a == nil { glog.Warningf("Authorization is disabled") return handler } return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - attrs, err := getAttribs.GetAttribs(req) + ctx, ok := requestContextMapper.Get(req) + if !ok { + internalError(w, req, errors.New("no context found for request")) + return + } + + attrs, err := GetAuthorizerAttributes(ctx) if err != nil { internalError(w, req, err) return @@ -54,28 +60,9 @@ func WithAuthorization(handler http.Handler, getAttribs RequestAttributeGetter, }) } -// RequestAttributeGetter is a function that extracts authorizer.Attributes from an http.Request -type RequestAttributeGetter interface { - GetAttribs(req *http.Request) (authorizer.Attributes, error) -} - -type requestAttributeGetter struct { - requestContextMapper api.RequestContextMapper -} - -// NewAttributeGetter returns an object which implements the RequestAttributeGetter interface. -func NewRequestAttributeGetter(requestContextMapper api.RequestContextMapper) RequestAttributeGetter { - return &requestAttributeGetter{requestContextMapper} -} - -func (r *requestAttributeGetter) GetAttribs(req *http.Request) (authorizer.Attributes, error) { +func GetAuthorizerAttributes(ctx api.Context) (authorizer.Attributes, error) { attribs := authorizer.AttributesRecord{} - ctx, ok := r.requestContextMapper.Get(req) - if !ok { - return nil, errors.New("no context found for request") - } - user, ok := api.UserFrom(ctx) if ok { attribs.User = user diff --git a/pkg/apiserver/filters/authorization_test.go b/pkg/apiserver/filters/authorization_test.go index 64181a7dac1..9334fcbdf1c 100644 --- a/pkg/apiserver/filters/authorization_test.go +++ b/pkg/apiserver/filters/authorization_test.go @@ -17,6 +17,7 @@ limitations under the License. package filters import ( + "errors" "net/http" "net/http/httptest" "reflect" @@ -27,9 +28,8 @@ import ( "k8s.io/kubernetes/pkg/auth/authorizer" ) -func TestGetAttribs(t *testing.T) { +func TestGetAuthorizerAttributes(t *testing.T) { mapper := api.NewRequestContextMapper() - attributeGetter := NewRequestAttributeGetter(mapper) testcases := map[string]struct { Verb string @@ -108,7 +108,12 @@ func TestGetAttribs(t *testing.T) { var attribs authorizer.Attributes var err error var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - attribs, err = attributeGetter.GetAttribs(req) + ctx, ok := mapper.Get(req) + if !ok { + internalError(w, req, errors.New("no context found for request")) + return + } + attribs, err = GetAuthorizerAttributes(ctx) }) handler = WithRequestInfo(handler, newTestRequestInfoResolver(), mapper) handler = api.WithRequestContext(handler, mapper) diff --git a/pkg/genericapiserver/config.go b/pkg/genericapiserver/config.go index 154e3a661eb..afdf8e942e8 100644 --- a/pkg/genericapiserver/config.go +++ b/pkg/genericapiserver/config.go @@ -485,8 +485,6 @@ func (c *Config) MaybeGenerateServingCerts(alternateIPs ...net.IP) error { } func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) (secure, insecure http.Handler) { - attributeGetter := apiserverfilters.NewRequestAttributeGetter(c.RequestContextMapper) - generic := func(handler http.Handler) http.Handler { handler = genericfilters.WithCORS(handler, c.CorsAllowedOriginList, nil, nil, nil, "true") handler = genericfilters.WithPanicRecovery(handler, c.RequestContextMapper) @@ -497,10 +495,10 @@ func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) (secure, insec return handler } audit := func(handler http.Handler) http.Handler { - return apiserverfilters.WithAudit(handler, attributeGetter, c.AuditWriter) + return apiserverfilters.WithAudit(handler, c.RequestContextMapper, c.AuditWriter) } protect := func(handler http.Handler) http.Handler { - handler = apiserverfilters.WithAuthorization(handler, attributeGetter, c.Authorizer) + handler = apiserverfilters.WithAuthorization(handler, c.RequestContextMapper, c.Authorizer) handler = apiserverfilters.WithImpersonation(handler, c.RequestContextMapper, c.Authorizer) handler = audit(handler) // before impersonation to read original user handler = authhandlers.WithAuthentication(handler, c.RequestContextMapper, c.Authenticator, authhandlers.Unauthorized(c.SupportsBasicAuth))