diff --git a/api/server/router/local/image.go b/api/server/router/local/image.go index c1d1e830db..f8fc04b2dd 100644 --- a/api/server/router/local/image.go +++ b/api/server/router/local/image.go @@ -7,9 +7,11 @@ import ( "fmt" "io" "net/http" + "net/url" "strings" "github.com/docker/distribution/digest" + "github.com/docker/distribution/registry/api/errcode" "github.com/docker/docker/api/server/httputils" "github.com/docker/docker/builder/dockerfile" 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) } } + // 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 var newRef reference.Named 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) } + +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 +} diff --git a/registry/registry.go b/registry/registry.go index f135cc1b7b..6214d41af3 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -28,7 +28,6 @@ var ( // ErrAlreadyExists is an error returned if an image being pushed // already exists on the remote side ErrAlreadyExists = errors.New("Image already exists") - errLoginRequired = errors.New("Authentication is required.") ) func init() { diff --git a/registry/session.go b/registry/session.go index 57acbc0cf6..4b18d0d1a1 100644 --- a/registry/session.go +++ b/registry/session.go @@ -19,6 +19,7 @@ import ( "strings" "github.com/Sirupsen/logrus" + "github.com/docker/distribution/registry/api/errcode" "github.com/docker/docker/pkg/httputils" "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/stringid" @@ -213,7 +214,7 @@ func (r *Session) GetRemoteHistory(imgID, registry string) ([]string, error) { defer res.Body.Close() if res.StatusCode != 200 { 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) } @@ -427,7 +428,7 @@ func (r *Session) GetRepositoryData(name reference.Named) (*RepositoryData, erro } defer res.Body.Close() if res.StatusCode == 401 { - return nil, errLoginRequired + return nil, errcode.ErrorCodeUnauthorized.WithArgs() } // TODO: Right now we're ignoring checksums in the response body. // 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() if res.StatusCode == 401 { - return nil, errLoginRequired + return nil, errcode.ErrorCodeUnauthorized.WithArgs() } var tokens, endpoints []string