Example #1
0
func (root *rootHandler) doAuth(ctx context.Context, imageName string, w http.ResponseWriter) (context.Context, error) {
	var access []auth.Access
	if imageName == "" {
		access = buildCatalogRecord(root.actions...)
	} else {
		access = buildAccessRecords(imageName, root.actions...)
	}

	log := ctxu.GetRequestLogger(ctx)
	var authCtx context.Context
	var err error
	if authCtx, err = root.auth.Authorized(ctx, access...); err != nil {
		if challenge, ok := err.(auth.Challenge); ok {
			// Let the challenge write the response.
			challenge.SetHeaders(w)

			if err := errcode.ServeJSON(w, errcode.ErrorCodeUnauthorized.WithDetail(access)); err != nil {
				log.Errorf("failed to serve challenge response: %s", err.Error())
				return nil, err
			}
			return nil, err
		}
		errcode.ServeJSON(w, errcode.ErrorCodeUnauthorized)
		return nil, err
	}
	return authCtx, nil
}
Example #2
0
// ServeHTTP serves an HTTP request and implements the http.Handler interface.
func (root *rootHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	ctx := ctxu.WithRequest(root.context, r)
	ctx, w = ctxu.WithResponseWriter(ctx, w)
	ctx = ctxu.WithLogger(ctx, ctxu.GetRequestLogger(ctx))
	ctx = context.WithValue(ctx, "repo", vars["imageName"])
	ctx = context.WithValue(ctx, "cryptoService", root.trust)

	defer func() {
		ctxu.GetResponseLogger(ctx).Info("response completed")
	}()

	if root.auth != nil {
		access := buildAccessRecords(vars["imageName"], root.actions...)
		var authCtx context.Context
		var err error
		if authCtx, err = root.auth.Authorized(ctx, access...); err != nil {
			if err, ok := err.(auth.Challenge); ok {
				err.ServeHTTP(w, r)
				w.WriteHeader(http.StatusUnauthorized)
				return
			}
			errcode.ServeJSON(w, v2.ErrorCodeUnauthorized)
			return
		}
		ctx = authCtx
	}
	if err := root.handler(ctx, w, r); err != nil {
		e := errcode.ServeJSON(w, err)
		if e != nil {
			logrus.Error(e)
		}
		return
	}
}
Example #3
0
// ServeHTTP serves an HTTP request and implements the http.Handler interface.
func (root *rootHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var (
		err  error
		ctx  = ctxu.WithRequest(root.context, r)
		log  = ctxu.GetRequestLogger(ctx)
		vars = mux.Vars(r)
	)
	ctx, w = ctxu.WithResponseWriter(ctx, w)
	ctx = ctxu.WithLogger(ctx, log)
	ctx = context.WithValue(ctx, notary.CtxKeyCryptoSvc, root.trust)

	defer func() {
		ctxu.GetResponseLogger(ctx).Info("response completed")
	}()

	if root.auth != nil {
		ctx = context.WithValue(ctx, notary.CtxKeyRepo, vars["imageName"])
		if ctx, err = root.doAuth(ctx, vars["imageName"], w); err != nil {
			// errors have already been logged/output to w inside doAuth
			// just return
			return
		}
	}
	if err := root.handler(ctx, w, r); err != nil {
		serveError(log, w, err)
	}
}
Example #4
0
// handlerWithContext wraps the given context-aware handler by setting up the
// request context from a base context.
func handlerWithContext(ctx context.Context, handler func(context.Context, http.ResponseWriter, *http.Request)) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx := context.WithRequest(ctx, r)
		logger := context.GetRequestLogger(ctx)
		ctx = context.WithLogger(ctx, logger)

		handler(ctx, w, r)
	})
}
Example #5
0
// ServeHTTP serves an HTTP request and implements the http.Handler interface.
func (root *rootHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	ctx := ctxu.WithRequest(root.context, r)
	log := ctxu.GetRequestLogger(ctx)
	ctx, w = ctxu.WithResponseWriter(ctx, w)
	ctx = ctxu.WithLogger(ctx, log)
	ctx = context.WithValue(ctx, "repo", vars["imageName"])
	ctx = context.WithValue(ctx, "cryptoService", root.trust)

	defer func() {
		ctxu.GetResponseLogger(ctx).Info("response completed")
	}()

	if root.auth != nil {
		access := buildAccessRecords(vars["imageName"], root.actions...)
		var authCtx context.Context
		var err error
		if authCtx, err = root.auth.Authorized(ctx, access...); err != nil {
			if challenge, ok := err.(auth.Challenge); ok {
				// Let the challenge write the response.
				challenge.SetHeaders(w)

				if err := errcode.ServeJSON(w, errcode.ErrorCodeUnauthorized.WithDetail(access)); err != nil {
					log.Errorf("failed to serve challenge response: %s", err.Error())
				}
				return
			}
			errcode.ServeJSON(w, errcode.ErrorCodeUnauthorized)
			return
		}
		ctx = authCtx
	}
	if err := root.handler(ctx, w, r); err != nil {
		if httpErr, ok := err.(errcode.ErrorCoder); ok {
			// info level logging for non-5XX http errors
			httpErrCode := httpErr.ErrorCode().Descriptor().HTTPStatusCode
			if httpErrCode >= http.StatusInternalServerError {
				// error level logging for 5XX http errors
				log.Error(httpErr)
			} else {
				log.Info(httpErr)
			}
		}
		e := errcode.ServeJSON(w, err)
		if e != nil {
			log.Error(e)
		}
		return
	}
}
Example #6
0
func (t *tokenHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	ctx := context.WithRequest(t.ctx, req)

	// If no authorization is provided, return a token the auth provider will treat as an anonymous user
	if len(req.Header.Get("Authorization")) == 0 {
		context.GetRequestLogger(ctx).Debugf("anonymous token request")
		t.writeToken(anonymousToken, w, req)
		return
	}

	// use the password as the token
	_, token, ok := req.BasicAuth()
	if !ok {
		context.GetRequestLogger(ctx).Debugf("no basic auth credentials provided")
		t.writeUnauthorized(w, req)
		return
	}

	// TODO: if this doesn't validate as an API token, attempt to obtain an API token using the given username/password
	copied := t.anonymousConfig
	copied.BearerToken = token
	osClient, err := client.New(&copied)
	if err != nil {
		context.GetRequestLogger(ctx).Errorf("error building client: %v", err)
		t.writeError(w, req)
		return
	}

	if _, err := osClient.Users().Get("~"); err != nil {
		context.GetRequestLogger(ctx).Debugf("invalid token: %v", err)
		t.writeUnauthorized(w, req)
		return
	}

	t.writeToken(token, w, req)
}
Example #7
0
// context either returns a new context or looks it up in the manager.
func (cm *contextManager) context(parent context.Context, w http.ResponseWriter, r *http.Request) context.Context {
	cm.mu.Lock()
	defer cm.mu.Unlock()

	ctx, ok := cm.contexts[r]
	if ok {
		return ctx
	}

	if parent == nil {
		parent = ctxu.Background()
	}

	ctx = ctxu.WithRequest(parent, r)
	ctx, w = ctxu.WithResponseWriter(ctx, w)
	ctx = ctxu.WithLogger(ctx, ctxu.GetRequestLogger(ctx))
	cm.contexts[r] = ctx

	return ctx
}