diff --git a/api/client/commands.go b/api/client/commands.go index 6eb440259832c..fbc90ff7149ab 100644 --- a/api/client/commands.go +++ b/api/client/commands.go @@ -1169,7 +1169,7 @@ func (cli *DockerCli) CmdPush(args ...string) error { return err } - signedBody, err := js.PrettySignature("buildSignatures") + signedBody, err := js.PrettySignature("signatures") if err != nil { return err } diff --git a/graph/manifest.go b/graph/manifest.go index 401aad8bdc175..7acf719346ea6 100644 --- a/graph/manifest.go +++ b/graph/manifest.go @@ -46,10 +46,13 @@ func (s *TagStore) CmdManifest(job *engine.Job) engine.Status { layersSeen := make(map[string]bool) layer, err := s.graph.Get(layerId) + if err != nil { + return job.Error(err) + } manifest.Architecture = layer.Architecture var metadata runconfig.Config metadata = *layer.Config - history := make(map[string]string) + history := make([]string, 0, cap(tarsums)) for ; layer != nil; layer, err = layer.GetParent() { if err != nil { @@ -83,7 +86,7 @@ func (s *TagStore) CmdManifest(job *engine.Job) engine.Status { if err != nil { return job.Error(fmt.Errorf("Cannot retrieve the path for {%s}: %s", layer.ID, err)) } - history[tarId] = string(jsonData) + history = append(history, string(jsonData)) } manifest.BlobSums = tarsums diff --git a/graph/pull.go b/graph/pull.go index fb8a8d8c469f4..121052ea18368 100644 --- a/graph/pull.go +++ b/graph/pull.go @@ -15,8 +15,33 @@ import ( "github.com/docker/docker/pkg/log" "github.com/docker/docker/registry" "github.com/docker/docker/utils" + "github.com/docker/libtrust" ) +func (s *TagStore) verifyManifest(manifestBytes []byte) (*registry.ManifestData, error) { + sig, err := libtrust.ParsePrettySignature(manifestBytes, "signatures") + if err != nil { + return nil, fmt.Errorf("error parsing payload: %s", err) + } + _, err = sig.Verify() + if err != nil { + return nil, fmt.Errorf("error verifying payload: %s", err) + } + + payload, err := sig.Payload() + if err != nil { + return nil, fmt.Errorf("error retrieving payload: %s", err) + } + + var manifest registry.ManifestData + err = json.Unmarshal(payload, &manifest) + if err != nil { + return nil, fmt.Errorf("error unmarshalling manifest: %s", err) + } + + return &manifest, nil +} + func (s *TagStore) CmdPull(job *engine.Job) engine.Status { if n := len(job.Args); n != 1 && n != 2 { return job.Errorf("Usage: %s IMAGE [TAG]", job.Name) @@ -84,42 +109,52 @@ func (s *TagStore) CmdPull(job *engine.Job) engine.Status { if err != nil { return job.Error(err) } - manifest := map[string]interface{}{} - err = json.Unmarshal(manifestBytes, &manifest) + + manifest, err := s.verifyManifest(manifestBytes) if err != nil { - return job.Error(err) + return job.Errorf("error verifying manifest: %s", err) } - log.Debugf("%#v", manifest["history"]) - h, ok := manifest["history"].(map[string]interface{}) - if !ok { - return job.Error(fmt.Errorf("manifest 'history' is not a map[string]string")) - } - log.Debugf("%#v", manifest["tarsum"]) - sums, ok := manifest["tarsum"].([]interface{}) - if !ok { - return job.Error(fmt.Errorf("manifest 'tarsum' is not a []string")) + + if len(manifest.BlobSums) != len(manifest.History) { + return job.Errorf("length of history not equal to number of layers") } - for _, sumInterface := range sums { - sumStr := sumInterface.(string) - jsonBytes := h[sumStr] - // - _ = jsonBytes.(string) + + for i := len(manifest.BlobSums) - 1; i >= 0; i-- { + sumStr := manifest.BlobSums[i] + imgJSON := []byte(manifest.History[i]) + + img, err := image.NewImgJSON(imgJSON) + if err != nil { + return job.Error(fmt.Errorf("failed to parse json: %s", err)) + } + chunks := strings.SplitN(sumStr, ":", 2) if len(chunks) < 2 { return job.Error(fmt.Errorf("expected 2 parts in the sumStr, got %#v", chunks)) } + sumType, checksum := chunks[0], chunks[1] + + log.Infof("pulling blob %q to V1 img %s", sumStr, img.ID) tmpFile, err := ioutil.TempFile("", "GetV2ImageBlob") if err != nil { - job.Error(err) + return job.Error(err) } - if err = r.GetV2ImageBlob(remoteName, chunks[0], chunks[1], tmpFile, nil); err != nil { - job.Error(err) + if err = r.GetV2ImageBlob(remoteName, sumType, checksum, tmpFile, nil); err != nil { + return job.Error(err) } fmt.Println(tmpFile) - } + tmpFile.Seek(0, 0) - log.Debugf("%#v", manifest["history"]) + err = s.graph.Register([]byte(imgJSON), tmpFile, img) + if err != nil { + return job.Error(err) + } + + if err = s.Set(localName, tag, img.ID, true); err != nil { + return job.Error(err) + } + } return engine.StatusOK // return from this pull, so we don't do a v1 pull } @@ -307,6 +342,7 @@ func (s *TagStore) pullImage(r *registry.Session, out io.Writer, imgID, endpoint continue } img, err = image.NewImgJSON(imgJSON) + // _RETURN HERE after getting image fom json if err != nil && j == retries { out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil)) return fmt.Errorf("Failed to parse json: %s", err) diff --git a/registry/session_prov.go b/registry/session_prov.go index 0eec9cab3698b..ef81d0562365b 100644 --- a/registry/session_prov.go +++ b/registry/session_prov.go @@ -198,11 +198,11 @@ func (r *Session) GetV2ImageBlob(imageName, sumType, sum string, blobWrtr io.Wri return err } defer res.Body.Close() - if res.StatusCode != 201 { + if res.StatusCode != 200 { if res.StatusCode == 401 { return errLoginRequired } - return utils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to push %s blob", res.StatusCode, imageName), res) + return utils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to pull %s blob", res.StatusCode, imageName), res) } _, err = io.Copy(blobWrtr, res.Body) diff --git a/registry/types.go b/registry/types.go index f71833f76be12..db246ab8edc5a 100644 --- a/registry/types.go +++ b/registry/types.go @@ -33,11 +33,11 @@ type RegistryInfo struct { } type ManifestData struct { - Name string `json:"name"` - Tag string `json:"tag"` - Architecture string `json:"architecture"` - BlobSums []string `json:"blobSums"` - History map[string]string `json:"history"` + Name string `json:"name"` + Tag string `json:"tag"` + Architecture string `json:"architecture"` + BlobSums []string `json:"blobSums"` + History []string `json:"history"` } type APIVersion int diff --git a/vendor/src/github.com/docker/libtrust b/vendor/src/github.com/docker/libtrust new file mode 160000 index 0000000000000..540d8fbb3dc14 --- /dev/null +++ b/vendor/src/github.com/docker/libtrust @@ -0,0 +1 @@ +Subproject commit 540d8fbb3dc145c58b0f3d44c1c41f087c6eacf5