diff --git a/registry/registry.go b/registry/registry.go index df94302305..7bdf12c883 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -2,6 +2,7 @@ package registry import ( "bytes" + "crypto/sha256" "encoding/json" "errors" "fmt" @@ -388,6 +389,7 @@ func (r *Registry) PushImageChecksumRegistry(imgData *ImgData, registry string, } setTokenAuth(req, token) req.Header.Set("X-Docker-Checksum", imgData.Checksum) + req.Header.Set("X-Docker-Checksum-Payload", imgData.ChecksumPayload) res, err := doWithCookies(r.client, req) if err != nil { @@ -446,26 +448,28 @@ func (r *Registry) PushImageJSONRegistry(imgData *ImgData, jsonRaw []byte, regis return nil } -func (r *Registry) PushImageLayerRegistry(imgID string, layer io.Reader, registry string, token []string, jsonRaw []byte) (checksum string, err error) { +func (r *Registry) PushImageLayerRegistry(imgID string, layer io.Reader, registry string, token []string, jsonRaw []byte) (checksum string, checksumPayload string, err error) { utils.Debugf("[registry] Calling PUT %s", registry+"images/"+imgID+"/layer") - tarsumLayer := &utils.TarSum{Reader: layer} + h := sha256.New() + checksumLayer := &utils.CheckSum{Reader: layer, Hash: h} + tarsumLayer := &utils.TarSum{Reader: checksumLayer} req, err := r.reqFactory.NewRequest("PUT", registry+"images/"+imgID+"/layer", tarsumLayer) if err != nil { - return "", err + return "", "", err } req.ContentLength = -1 req.TransferEncoding = []string{"chunked"} setTokenAuth(req, token) res, err := doWithCookies(r.client, req) if err != nil { - return "", fmt.Errorf("Failed to upload layer: %s", err) + return "", "", fmt.Errorf("Failed to upload layer: %s", err) } if rc, ok := layer.(io.Closer); ok { if err := rc.Close(); err != nil { - return "", err + return "", "", err } } defer res.Body.Close() @@ -473,11 +477,13 @@ func (r *Registry) PushImageLayerRegistry(imgID string, layer io.Reader, registr if res.StatusCode != 200 { errBody, err := ioutil.ReadAll(res.Body) if err != nil { - return "", utils.NewHTTPRequestError(fmt.Sprintf("HTTP code %d while uploading metadata and error when trying to parse response body: %s", res.StatusCode, err), res) + return "", "", utils.NewHTTPRequestError(fmt.Sprintf("HTTP code %d while uploading metadata and error when trying to parse response body: %s", res.StatusCode, err), res) } - return "", utils.NewHTTPRequestError(fmt.Sprintf("Received HTTP code %d while uploading layer: %s", res.StatusCode, errBody), res) + return "", "", utils.NewHTTPRequestError(fmt.Sprintf("Received HTTP code %d while uploading layer: %s", res.StatusCode, errBody), res) } - return tarsumLayer.Sum(jsonRaw), nil + + checksumPayload = "sha256:" + checksumLayer.Sum() + return tarsumLayer.Sum(jsonRaw), checksumPayload, nil } // push a tag on the registry. @@ -671,9 +677,10 @@ type RepositoryData struct { } type ImgData struct { - ID string `json:"id"` - Checksum string `json:"checksum,omitempty"` - Tag string `json:",omitempty"` + ID string `json:"id"` + Checksum string `json:"checksum,omitempty"` + ChecksumPayload string `json:"checksum,omitempty"` + Tag string `json:",omitempty"` } type Registry struct { diff --git a/server.go b/server.go index 0ed96fee31..b9fd92716a 100644 --- a/server.go +++ b/server.go @@ -1504,11 +1504,12 @@ func (srv *Server) pushImage(r *registry.Registry, out io.Writer, remote, imgID, defer os.RemoveAll(layerData.Name()) // Send the layer - checksum, err = r.PushImageLayerRegistry(imgData.ID, utils.ProgressReader(layerData, int(layerData.Size), out, sf, false, utils.TruncateID(imgData.ID), "Pushing"), ep, token, jsonRaw) + checksum, checksumPayload, err := r.PushImageLayerRegistry(imgData.ID, utils.ProgressReader(layerData, int(layerData.Size), out, sf, false, utils.TruncateID(imgData.ID), "Pushing"), ep, token, jsonRaw) if err != nil { return "", err } imgData.Checksum = checksum + imgData.ChecksumPayload = checksumPayload // Send the checksum if err := r.PushImageChecksumRegistry(imgData, ep, token); err != nil { return "", err diff --git a/utils/checksum.go b/utils/checksum.go new file mode 100644 index 0000000000..1c85aa63a3 --- /dev/null +++ b/utils/checksum.go @@ -0,0 +1,24 @@ +package utils + +import ( + "encoding/hex" + "hash" + "io" +) + +type CheckSum struct { + io.Reader + Hash hash.Hash +} + +func (cs *CheckSum) Read(buf []byte) (int, error) { + n, err := cs.Reader.Read(buf) + if err == nil { + cs.Hash.Write(buf[:n]) + } + return n, err +} + +func (cs *CheckSum) Sum() string { + return hex.EncodeToString(cs.Hash.Sum(nil)) +}