github.com/bdehamer/docker@v1.5.0/graph/manifest.go (about) 1 package graph 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io" 8 "io/ioutil" 9 10 log "github.com/Sirupsen/logrus" 11 "github.com/docker/docker/engine" 12 "github.com/docker/docker/pkg/tarsum" 13 "github.com/docker/docker/registry" 14 "github.com/docker/docker/runconfig" 15 "github.com/docker/libtrust" 16 ) 17 18 func (s *TagStore) newManifest(localName, remoteName, tag string) ([]byte, error) { 19 manifest := ®istry.ManifestData{ 20 Name: remoteName, 21 Tag: tag, 22 SchemaVersion: 1, 23 } 24 localRepo, err := s.Get(localName) 25 if err != nil { 26 return nil, err 27 } 28 if localRepo == nil { 29 return nil, fmt.Errorf("Repo does not exist: %s", localName) 30 } 31 32 // Get the top-most layer id which the tag points to 33 layerId, exists := localRepo[tag] 34 if !exists { 35 return nil, fmt.Errorf("Tag does not exist for %s: %s", localName, tag) 36 } 37 layersSeen := make(map[string]bool) 38 39 layer, err := s.graph.Get(layerId) 40 if err != nil { 41 return nil, err 42 } 43 manifest.Architecture = layer.Architecture 44 manifest.FSLayers = make([]*registry.FSLayer, 0, 4) 45 manifest.History = make([]*registry.ManifestHistory, 0, 4) 46 var metadata runconfig.Config 47 if layer.Config != nil { 48 metadata = *layer.Config 49 } 50 51 for ; layer != nil; layer, err = layer.GetParent() { 52 if err != nil { 53 return nil, err 54 } 55 56 if layersSeen[layer.ID] { 57 break 58 } 59 if layer.Config != nil && metadata.Image != layer.ID { 60 err = runconfig.Merge(&metadata, layer.Config) 61 if err != nil { 62 return nil, err 63 } 64 } 65 66 checksum, err := layer.GetCheckSum(s.graph.ImageRoot(layer.ID)) 67 if err != nil { 68 return nil, fmt.Errorf("Error getting image checksum: %s", err) 69 } 70 if tarsum.VersionLabelForChecksum(checksum) != tarsum.Version1.String() { 71 archive, err := layer.TarLayer() 72 if err != nil { 73 return nil, err 74 } 75 76 tarSum, err := tarsum.NewTarSum(archive, true, tarsum.Version1) 77 if err != nil { 78 return nil, err 79 } 80 if _, err := io.Copy(ioutil.Discard, tarSum); err != nil { 81 return nil, err 82 } 83 84 checksum = tarSum.Sum(nil) 85 86 // Save checksum value 87 if err := layer.SaveCheckSum(s.graph.ImageRoot(layer.ID), checksum); err != nil { 88 return nil, err 89 } 90 } 91 92 jsonData, err := layer.RawJson() 93 if err != nil { 94 return nil, fmt.Errorf("Cannot retrieve the path for {%s}: %s", layer.ID, err) 95 } 96 97 manifest.FSLayers = append(manifest.FSLayers, ®istry.FSLayer{BlobSum: checksum}) 98 99 layersSeen[layer.ID] = true 100 101 manifest.History = append(manifest.History, ®istry.ManifestHistory{V1Compatibility: string(jsonData)}) 102 } 103 104 manifestBytes, err := json.MarshalIndent(manifest, "", " ") 105 if err != nil { 106 return nil, err 107 } 108 109 return manifestBytes, nil 110 } 111 112 // loadManifest loads a manifest from a byte array and verifies its content. 113 // The signature must be verified or an error is returned. If the manifest 114 // contains no signatures by a trusted key for the name in the manifest, the 115 // image is not considered verified. The parsed manifest object and a boolean 116 // for whether the manifest is verified is returned. 117 func (s *TagStore) loadManifest(eng *engine.Engine, manifestBytes []byte) (*registry.ManifestData, bool, error) { 118 sig, err := libtrust.ParsePrettySignature(manifestBytes, "signatures") 119 if err != nil { 120 return nil, false, fmt.Errorf("error parsing payload: %s", err) 121 } 122 123 keys, err := sig.Verify() 124 if err != nil { 125 return nil, false, fmt.Errorf("error verifying payload: %s", err) 126 } 127 128 payload, err := sig.Payload() 129 if err != nil { 130 return nil, false, fmt.Errorf("error retrieving payload: %s", err) 131 } 132 133 var manifest registry.ManifestData 134 if err := json.Unmarshal(payload, &manifest); err != nil { 135 return nil, false, fmt.Errorf("error unmarshalling manifest: %s", err) 136 } 137 if manifest.SchemaVersion != 1 { 138 return nil, false, fmt.Errorf("unsupported schema version: %d", manifest.SchemaVersion) 139 } 140 141 var verified bool 142 for _, key := range keys { 143 job := eng.Job("trust_key_check") 144 b, err := key.MarshalJSON() 145 if err != nil { 146 return nil, false, fmt.Errorf("error marshalling public key: %s", err) 147 } 148 namespace := manifest.Name 149 if namespace[0] != '/' { 150 namespace = "/" + namespace 151 } 152 stdoutBuffer := bytes.NewBuffer(nil) 153 154 job.Args = append(job.Args, namespace) 155 job.Setenv("PublicKey", string(b)) 156 // Check key has read/write permission (0x03) 157 job.SetenvInt("Permission", 0x03) 158 job.Stdout.Add(stdoutBuffer) 159 if err = job.Run(); err != nil { 160 return nil, false, fmt.Errorf("error running key check: %s", err) 161 } 162 result := engine.Tail(stdoutBuffer, 1) 163 log.Debugf("Key check result: %q", result) 164 if result == "verified" { 165 verified = true 166 } 167 } 168 169 return &manifest, verified, nil 170 } 171 172 func checkValidManifest(manifest *registry.ManifestData) error { 173 if len(manifest.FSLayers) != len(manifest.History) { 174 return fmt.Errorf("length of history not equal to number of layers") 175 } 176 177 if len(manifest.FSLayers) == 0 { 178 return fmt.Errorf("no FSLayers in manifest") 179 } 180 181 return nil 182 }