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 <josh.hawn@docker.com> (github: jlhawn)
This commit is contained in:
Josh Hawn 2015-02-03 17:59:24 -08:00
parent 1089cae282
commit 904b35a24f
2 changed files with 18 additions and 5 deletions

View File

@ -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)

View File

@ -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