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