|
@@ -1,8 +1,6 @@
|
|
package graph
|
|
package graph
|
|
|
|
|
|
import (
|
|
import (
|
|
- "bytes"
|
|
|
|
- "encoding/json"
|
|
|
|
"fmt"
|
|
"fmt"
|
|
"io"
|
|
"io"
|
|
"io/ioutil"
|
|
"io/ioutil"
|
|
@@ -18,63 +16,8 @@ import (
|
|
"github.com/docker/docker/pkg/tarsum"
|
|
"github.com/docker/docker/pkg/tarsum"
|
|
"github.com/docker/docker/registry"
|
|
"github.com/docker/docker/registry"
|
|
"github.com/docker/docker/utils"
|
|
"github.com/docker/docker/utils"
|
|
- "github.com/docker/libtrust"
|
|
|
|
)
|
|
)
|
|
|
|
|
|
-func (s *TagStore) verifyManifest(eng *engine.Engine, manifestBytes []byte) (*registry.ManifestData, bool, error) {
|
|
|
|
- sig, err := libtrust.ParsePrettySignature(manifestBytes, "signatures")
|
|
|
|
- if err != nil {
|
|
|
|
- return nil, false, fmt.Errorf("error parsing payload: %s", err)
|
|
|
|
- }
|
|
|
|
- keys, err := sig.Verify()
|
|
|
|
- if err != nil {
|
|
|
|
- return nil, false, fmt.Errorf("error verifying payload: %s", err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- payload, err := sig.Payload()
|
|
|
|
- if err != nil {
|
|
|
|
- return nil, false, fmt.Errorf("error retrieving payload: %s", err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- var manifest registry.ManifestData
|
|
|
|
- if err := json.Unmarshal(payload, &manifest); err != nil {
|
|
|
|
- return nil, false, fmt.Errorf("error unmarshalling manifest: %s", err)
|
|
|
|
- }
|
|
|
|
- if manifest.SchemaVersion != 1 {
|
|
|
|
- return nil, false, fmt.Errorf("unsupported schema version: %d", manifest.SchemaVersion)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- var verified bool
|
|
|
|
- for _, key := range keys {
|
|
|
|
- job := eng.Job("trust_key_check")
|
|
|
|
- b, err := key.MarshalJSON()
|
|
|
|
- if err != nil {
|
|
|
|
- return nil, false, fmt.Errorf("error marshalling public key: %s", err)
|
|
|
|
- }
|
|
|
|
- namespace := manifest.Name
|
|
|
|
- if namespace[0] != '/' {
|
|
|
|
- namespace = "/" + namespace
|
|
|
|
- }
|
|
|
|
- stdoutBuffer := bytes.NewBuffer(nil)
|
|
|
|
-
|
|
|
|
- job.Args = append(job.Args, namespace)
|
|
|
|
- job.Setenv("PublicKey", string(b))
|
|
|
|
- // Check key has read/write permission (0x03)
|
|
|
|
- job.SetenvInt("Permission", 0x03)
|
|
|
|
- job.Stdout.Add(stdoutBuffer)
|
|
|
|
- if err = job.Run(); err != nil {
|
|
|
|
- return nil, false, fmt.Errorf("error running key check: %s", err)
|
|
|
|
- }
|
|
|
|
- result := engine.Tail(stdoutBuffer, 1)
|
|
|
|
- log.Debugf("Key check result: %q", result)
|
|
|
|
- if result == "verified" {
|
|
|
|
- verified = true
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return &manifest, verified, nil
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
func (s *TagStore) CmdPull(job *engine.Job) engine.Status {
|
|
func (s *TagStore) CmdPull(job *engine.Job) engine.Status {
|
|
if n := len(job.Args); n != 1 && n != 2 {
|
|
if n := len(job.Args); n != 1 && n != 2 {
|
|
return job.Errorf("Usage: %s IMAGE [TAG]", job.Name)
|
|
return job.Errorf("Usage: %s IMAGE [TAG]", job.Name)
|
|
@@ -113,7 +56,6 @@ func (s *TagStore) CmdPull(job *engine.Job) engine.Status {
|
|
}
|
|
}
|
|
defer s.poolRemove("pull", repoInfo.LocalName+":"+tag)
|
|
defer s.poolRemove("pull", repoInfo.LocalName+":"+tag)
|
|
|
|
|
|
-
|
|
|
|
log.Debugf("pulling image from host %q with remote name %q", repoInfo.Index.Name, repoInfo.RemoteName)
|
|
log.Debugf("pulling image from host %q with remote name %q", repoInfo.Index.Name, repoInfo.RemoteName)
|
|
endpoint, err := repoInfo.GetEndpoint()
|
|
endpoint, err := repoInfo.GetEndpoint()
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -484,8 +426,8 @@ func (s *TagStore) pullV2Tag(eng *engine.Engine, r *registry.Session, out io.Wri
|
|
return false, fmt.Errorf("error verifying manifest: %s", err)
|
|
return false, fmt.Errorf("error verifying manifest: %s", err)
|
|
}
|
|
}
|
|
|
|
|
|
- if len(manifest.FSLayers) != len(manifest.History) {
|
|
|
|
- return false, fmt.Errorf("length of history not equal to number of layers")
|
|
|
|
|
|
+ if err := checkValidManifest(manifest); err != nil {
|
|
|
|
+ return false, err
|
|
}
|
|
}
|
|
|
|
|
|
if verified {
|
|
if verified {
|
|
@@ -493,11 +435,6 @@ func (s *TagStore) pullV2Tag(eng *engine.Engine, r *registry.Session, out io.Wri
|
|
} else {
|
|
} else {
|
|
out.Write(sf.FormatStatus(tag, "Pulling from %s", repoInfo.CanonicalName))
|
|
out.Write(sf.FormatStatus(tag, "Pulling from %s", repoInfo.CanonicalName))
|
|
}
|
|
}
|
|
-
|
|
|
|
- if len(manifest.FSLayers) == 0 {
|
|
|
|
- return false, fmt.Errorf("no blobSums in manifest")
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
downloads := make([]downloadInfo, len(manifest.FSLayers))
|
|
downloads := make([]downloadInfo, len(manifest.FSLayers))
|
|
|
|
|
|
for i := len(manifest.FSLayers) - 1; i >= 0; i-- {
|
|
for i := len(manifest.FSLayers) - 1; i >= 0; i-- {
|