distribution/storage/manifest.go

126 lines
3.2 KiB
Go

package storage
import (
"encoding/json"
"fmt"
"github.com/docker/libtrust"
"github.com/docker/docker-registry/digest"
)
var (
// ErrManifestUnknown is returned if the manifest is not known by the
// registry.
ErrManifestUnknown = fmt.Errorf("unknown manifest")
// ErrManifestUnverified is returned when the registry is unable to verify
// the manifest.
ErrManifestUnverified = fmt.Errorf("unverified manifest")
)
// Versioned provides a struct with just the manifest schemaVersion. Incoming
// content with unknown schema version can be decoded against this struct to
// check the version.
type Versioned struct {
// SchemaVersion is the image manifest schema that this image follows
SchemaVersion int `json:"schemaVersion"`
}
// Manifest provides the base accessible fields for working with V2 image
// format in the registry.
type Manifest struct {
Versioned
// Name is the name of the image's repository
Name string `json:"name"`
// Tag is the tag of the image specified by this manifest
Tag string `json:"tag"`
// Architecture is the host architecture on which this image is intended to
// run
Architecture string `json:"architecture"`
// FSLayers is a list of filesystem layer blobSums contained in this image
FSLayers []FSLayer `json:"fsLayers"`
// History is a list of unstructured historical data for v1 compatibility
History []ManifestHistory `json:"history"`
}
// Sign signs the manifest with the provided private key, returning a
// SignedManifest. This typically won't be used within the registry, except
// for testing.
func (m *Manifest) Sign(pk libtrust.PrivateKey) (*SignedManifest, error) {
p, err := json.Marshal(m)
if err != nil {
return nil, err
}
js, err := libtrust.NewJSONSignature(p)
if err != nil {
return nil, err
}
if err := js.Sign(pk); err != nil {
return nil, err
}
pretty, err := js.PrettySignature("signatures")
if err != nil {
return nil, err
}
return &SignedManifest{
Manifest: *m,
Raw: pretty,
}, nil
}
// SignedManifest provides an envelope for
type SignedManifest struct {
Manifest
// Raw is the byte representation of the ImageManifest, used for signature
// verification. The manifest byte representation cannot change or it will
// have to be re-signed.
Raw []byte `json:"-"`
}
// UnmarshalJSON populates a new ImageManifest struct from JSON data.
func (m *SignedManifest) UnmarshalJSON(b []byte) error {
var manifest Manifest
if err := json.Unmarshal(b, &manifest); err != nil {
return err
}
m.Manifest = manifest
m.Raw = b
return nil
}
// MarshalJSON returns the contents of raw. If Raw is nil, marshals the inner
// contents.
func (m *SignedManifest) MarshalJSON() ([]byte, error) {
if len(m.Raw) > 0 {
return m.Raw, nil
}
// If the raw data is not available, just dump the inner content.
return json.Marshal(&m.Manifest)
}
// FSLayer is a container struct for BlobSums defined in an image manifest
type FSLayer struct {
// BlobSum is the tarsum of the referenced filesystem image layer
BlobSum digest.Digest `json:"blobSum"`
}
// ManifestHistory stores unstructured v1 compatibility information
type ManifestHistory struct {
// V1Compatibility is the raw v1 compatibility information
V1Compatibility string `json:"v1Compatibility"`
}