github.com/powellquiring/docker@v1.6.0-rc1/graph/manifest.go (about) 1 package graph 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 8 log "github.com/Sirupsen/logrus" 9 "github.com/docker/distribution/digest" 10 "github.com/docker/docker/engine" 11 "github.com/docker/docker/registry" 12 "github.com/docker/docker/utils" 13 "github.com/docker/libtrust" 14 ) 15 16 // loadManifest loads a manifest from a byte array and verifies its content. 17 // The signature must be verified or an error is returned. If the manifest 18 // contains no signatures by a trusted key for the name in the manifest, the 19 // image is not considered verified. The parsed manifest object and a boolean 20 // for whether the manifest is verified is returned. 21 func (s *TagStore) loadManifest(eng *engine.Engine, manifestBytes []byte, dgst, ref string) (*registry.ManifestData, bool, error) { 22 sig, err := libtrust.ParsePrettySignature(manifestBytes, "signatures") 23 if err != nil { 24 return nil, false, fmt.Errorf("error parsing payload: %s", err) 25 } 26 27 keys, err := sig.Verify() 28 if err != nil { 29 return nil, false, fmt.Errorf("error verifying payload: %s", err) 30 } 31 32 payload, err := sig.Payload() 33 if err != nil { 34 return nil, false, fmt.Errorf("error retrieving payload: %s", err) 35 } 36 37 var manifestDigest digest.Digest 38 39 if dgst != "" { 40 manifestDigest, err = digest.ParseDigest(dgst) 41 if err != nil { 42 return nil, false, fmt.Errorf("invalid manifest digest from registry: %s", err) 43 } 44 45 dgstVerifier, err := digest.NewDigestVerifier(manifestDigest) 46 if err != nil { 47 return nil, false, fmt.Errorf("unable to verify manifest digest from registry: %s", err) 48 } 49 50 dgstVerifier.Write(payload) 51 52 if !dgstVerifier.Verified() { 53 computedDigest, _ := digest.FromBytes(payload) 54 return nil, false, fmt.Errorf("unable to verify manifest digest: registry has %q, computed %q", manifestDigest, computedDigest) 55 } 56 } 57 58 if utils.DigestReference(ref) && ref != manifestDigest.String() { 59 return nil, false, fmt.Errorf("mismatching image manifest digest: got %q, expected %q", manifestDigest, ref) 60 } 61 62 var manifest registry.ManifestData 63 if err := json.Unmarshal(payload, &manifest); err != nil { 64 return nil, false, fmt.Errorf("error unmarshalling manifest: %s", err) 65 } 66 if manifest.SchemaVersion != 1 { 67 return nil, false, fmt.Errorf("unsupported schema version: %d", manifest.SchemaVersion) 68 } 69 70 var verified bool 71 for _, key := range keys { 72 job := eng.Job("trust_key_check") 73 b, err := key.MarshalJSON() 74 if err != nil { 75 return nil, false, fmt.Errorf("error marshalling public key: %s", err) 76 } 77 namespace := manifest.Name 78 if namespace[0] != '/' { 79 namespace = "/" + namespace 80 } 81 stdoutBuffer := bytes.NewBuffer(nil) 82 83 job.Args = append(job.Args, namespace) 84 job.Setenv("PublicKey", string(b)) 85 // Check key has read/write permission (0x03) 86 job.SetenvInt("Permission", 0x03) 87 job.Stdout.Add(stdoutBuffer) 88 if err = job.Run(); err != nil { 89 return nil, false, fmt.Errorf("error running key check: %s", err) 90 } 91 result := engine.Tail(stdoutBuffer, 1) 92 log.Debugf("Key check result: %q", result) 93 if result == "verified" { 94 verified = true 95 } 96 } 97 98 return &manifest, verified, nil 99 } 100 101 func checkValidManifest(manifest *registry.ManifestData) error { 102 if len(manifest.FSLayers) != len(manifest.History) { 103 return fmt.Errorf("length of history not equal to number of layers") 104 } 105 106 if len(manifest.FSLayers) == 0 { 107 return fmt.Errorf("no FSLayers in manifest") 108 } 109 110 return nil 111 }