Parcourir la source

Respond with 401 when there is an unauthorized error from the registry.

Signed-off-by: David Calavera <david.calavera@gmail.com>
David Calavera il y a 9 ans
Parent
commit
7bca932182
3 fichiers modifiés avec 25 ajouts et 4 suppressions
  1. 21 0
      api/server/router/local/image.go
  2. 0 1
      registry/registry.go
  3. 4 3
      registry/session.go

+ 21 - 0
api/server/router/local/image.go

@@ -7,9 +7,11 @@ import (
 	"fmt"
 	"fmt"
 	"io"
 	"io"
 	"net/http"
 	"net/http"
+	"net/url"
 	"strings"
 	"strings"
 
 
 	"github.com/docker/distribution/digest"
 	"github.com/docker/distribution/digest"
+	"github.com/docker/distribution/registry/api/errcode"
 	"github.com/docker/docker/api/server/httputils"
 	"github.com/docker/docker/api/server/httputils"
 	"github.com/docker/docker/builder/dockerfile"
 	"github.com/docker/docker/builder/dockerfile"
 	derr "github.com/docker/docker/errors"
 	derr "github.com/docker/docker/errors"
@@ -137,6 +139,12 @@ func (s *router) postImagesCreate(ctx context.Context, w http.ResponseWriter, r
 				err = s.daemon.PullImage(ref, metaHeaders, authConfig, output)
 				err = s.daemon.PullImage(ref, metaHeaders, authConfig, output)
 			}
 			}
 		}
 		}
+		// Check the error from pulling an image to make sure the request
+		// was authorized. Modify the status if the request was
+		// unauthorized to respond with 401 rather than 500.
+		if err != nil && isAuthorizedError(err) {
+			err = errcode.ErrorCodeUnauthorized.WithMessage(fmt.Sprintf("Authentication is required: %s", err))
+		}
 	} else { //import
 	} else { //import
 		var newRef reference.Named
 		var newRef reference.Named
 		if repo != "" {
 		if repo != "" {
@@ -373,3 +381,16 @@ func (s *router) getImagesSearch(ctx context.Context, w http.ResponseWriter, r *
 	}
 	}
 	return httputils.WriteJSON(w, http.StatusOK, query.Results)
 	return httputils.WriteJSON(w, http.StatusOK, query.Results)
 }
 }
+
+func isAuthorizedError(err error) bool {
+	if urlError, ok := err.(*url.Error); ok {
+		err = urlError.Err
+	}
+
+	if dError, ok := err.(errcode.Error); ok {
+		if dError.ErrorCode() == errcode.ErrorCodeUnauthorized {
+			return true
+		}
+	}
+	return false
+}

+ 0 - 1
registry/registry.go

@@ -28,7 +28,6 @@ var (
 	// ErrAlreadyExists is an error returned if an image being pushed
 	// ErrAlreadyExists is an error returned if an image being pushed
 	// already exists on the remote side
 	// already exists on the remote side
 	ErrAlreadyExists = errors.New("Image already exists")
 	ErrAlreadyExists = errors.New("Image already exists")
-	errLoginRequired = errors.New("Authentication is required.")
 )
 )
 
 
 func init() {
 func init() {

+ 4 - 3
registry/session.go

@@ -19,6 +19,7 @@ import (
 	"strings"
 	"strings"
 
 
 	"github.com/Sirupsen/logrus"
 	"github.com/Sirupsen/logrus"
+	"github.com/docker/distribution/registry/api/errcode"
 	"github.com/docker/docker/pkg/httputils"
 	"github.com/docker/docker/pkg/httputils"
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/docker/docker/pkg/stringid"
@@ -213,7 +214,7 @@ func (r *Session) GetRemoteHistory(imgID, registry string) ([]string, error) {
 	defer res.Body.Close()
 	defer res.Body.Close()
 	if res.StatusCode != 200 {
 	if res.StatusCode != 200 {
 		if res.StatusCode == 401 {
 		if res.StatusCode == 401 {
-			return nil, errLoginRequired
+			return nil, errcode.ErrorCodeUnauthorized.WithArgs()
 		}
 		}
 		return nil, httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to fetch remote history for %s", res.StatusCode, imgID), res)
 		return nil, httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to fetch remote history for %s", res.StatusCode, imgID), res)
 	}
 	}
@@ -427,7 +428,7 @@ func (r *Session) GetRepositoryData(name reference.Named) (*RepositoryData, erro
 	}
 	}
 	defer res.Body.Close()
 	defer res.Body.Close()
 	if res.StatusCode == 401 {
 	if res.StatusCode == 401 {
-		return nil, errLoginRequired
+		return nil, errcode.ErrorCodeUnauthorized.WithArgs()
 	}
 	}
 	// TODO: Right now we're ignoring checksums in the response body.
 	// TODO: Right now we're ignoring checksums in the response body.
 	// In the future, we need to use them to check image validity.
 	// In the future, we need to use them to check image validity.
@@ -661,7 +662,7 @@ func (r *Session) PushImageJSONIndex(remote reference.Named, imgList []*ImgData,
 	defer res.Body.Close()
 	defer res.Body.Close()
 
 
 	if res.StatusCode == 401 {
 	if res.StatusCode == 401 {
-		return nil, errLoginRequired
+		return nil, errcode.ErrorCodeUnauthorized.WithArgs()
 	}
 	}
 
 
 	var tokens, endpoints []string
 	var tokens, endpoints []string