From 904b35a24f80c08b42ca1f6e737fd3903ec744a5 Mon Sep 17 00:00:00 2001 From: Josh Hawn Date: Tue, 3 Feb 2015 17:59:24 -0800 Subject: [PATCH] Use context for auth access controllers The auth package has been updated to use "golang.org/x/net/context" for passing information between the application and the auth backend. AccessControllers should now set a "auth.user" context value to a AuthUser struct containing a single "Name" field for now with possible, optional, values in the future. The "silly" auth backend always sets the name to "silly", while the "token" auth backend will set the name to match the "subject" claim of the JWT. Docker-DCO-1.1-Signed-off-by: Josh Hawn (github: jlhawn) --- docs/app.go | 19 ++++++++++++++----- docs/context.go | 4 ++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/docs/app.go b/docs/app.go index 53759a1e..6e5480c3 100644 --- a/docs/app.go +++ b/docs/app.go @@ -16,6 +16,7 @@ import ( "github.com/docker/distribution/storagedriver" "github.com/docker/distribution/storagedriver/factory" "github.com/gorilla/mux" + "golang.org/x/net/context" ) // App is a global registry application object. Shared resources can be placed @@ -189,6 +190,12 @@ func (ssrw *singleStatusResponseWriter) WriteHeader(status int) { ssrw.ResponseWriter.WriteHeader(status) } +// WithRequest adds an http request to the given context and requents +// a new context with an "http.request" value. +func WithRequest(ctx context.Context, r *http.Request) context.Context { + return context.WithValue(ctx, "http.request", r) +} + // dispatcher returns a handler that constructs a request specific context and // handler, using the dispatch factory function. func (app *App) dispatcher(dispatch dispatchFunc) http.Handler { @@ -301,7 +308,8 @@ func (app *App) authorized(w http.ResponseWriter, r *http.Request, context *Cont } } - if err := app.accessController.Authorized(r, accessRecords...); err != nil { + authCtx, err := app.accessController.Authorized(WithRequest(nil, r), accessRecords...) + if err != nil { switch err := err.(type) { case auth.Challenge: w.Header().Set("Content-Type", "application/json; charset=utf-8") @@ -322,6 +330,10 @@ func (app *App) authorized(w http.ResponseWriter, r *http.Request, context *Cont return err } + // The authorized context should contain an auth.UserInfo + // object. If it doesn't, just use the zero value for now. + context.AuthUserInfo, _ = authCtx.Value("auth.user").(auth.UserInfo) + // At this point, the request should have access to the repository under // the requested operation. Make is available on the context. context.Repository = app.registry.Repository(repo) @@ -332,11 +344,8 @@ func (app *App) authorized(w http.ResponseWriter, r *http.Request, context *Cont // eventBridge returns a bridge for the current request, configured with the // correct actor and source. func (app *App) eventBridge(ctx *Context, r *http.Request) notifications.Listener { - // TODO(stevvooe): Need to extract user data from request context using - // auth system. Would prefer to do this during logging refactor and - // addition of user and google context type. actor := notifications.ActorRecord{ - Name: "--todo--", + Name: ctx.AuthUserInfo.Name, } request := notifications.NewRequestRecord(ctx.RequestID, r) diff --git a/docs/context.go b/docs/context.go index eaa603a8..150e5de6 100644 --- a/docs/context.go +++ b/docs/context.go @@ -3,6 +3,7 @@ package registry import ( "github.com/Sirupsen/logrus" "github.com/docker/distribution/api/v2" + "github.com/docker/distribution/auth" "github.com/docker/distribution/storage" ) @@ -25,6 +26,9 @@ type Context struct { // handler *must not* start the response via http.ResponseWriter. Errors v2.Errors + // AuthUserInfo contains information about an authorized client. + AuthUserInfo auth.UserInfo + // vars contains the extracted gorilla/mux variables that can be used for // assignment. vars map[string]string