github.com/lusis/distribution@v2.0.1+incompatible/registry/storage/manifeststore.go (about)

     1  package storage
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/docker/distribution"
     7  	ctxu "github.com/docker/distribution/context"
     8  	"github.com/docker/distribution/digest"
     9  	"github.com/docker/distribution/manifest"
    10  	"github.com/docker/libtrust"
    11  )
    12  
    13  type manifestStore struct {
    14  	repository *repository
    15  
    16  	revisionStore *revisionStore
    17  	tagStore      *tagStore
    18  }
    19  
    20  var _ distribution.ManifestService = &manifestStore{}
    21  
    22  func (ms *manifestStore) Exists(dgst digest.Digest) (bool, error) {
    23  	ctxu.GetLogger(ms.repository.ctx).Debug("(*manifestStore).Exists")
    24  	return ms.revisionStore.exists(dgst)
    25  }
    26  
    27  func (ms *manifestStore) Get(dgst digest.Digest) (*manifest.SignedManifest, error) {
    28  	ctxu.GetLogger(ms.repository.ctx).Debug("(*manifestStore).Get")
    29  	return ms.revisionStore.get(dgst)
    30  }
    31  
    32  func (ms *manifestStore) Put(manifest *manifest.SignedManifest) error {
    33  	ctxu.GetLogger(ms.repository.ctx).Debug("(*manifestStore).Put")
    34  
    35  	// TODO(stevvooe): Add check here to see if the revision is already
    36  	// present in the repository. If it is, we should merge the signatures, do
    37  	// a shallow verify (or a full one, doesn't matter) and return an error
    38  	// indicating what happened.
    39  
    40  	// Verify the manifest.
    41  	if err := ms.verifyManifest(manifest); err != nil {
    42  		return err
    43  	}
    44  
    45  	// Store the revision of the manifest
    46  	revision, err := ms.revisionStore.put(manifest)
    47  	if err != nil {
    48  		return err
    49  	}
    50  
    51  	// Now, tag the manifest
    52  	return ms.tagStore.tag(manifest.Tag, revision)
    53  }
    54  
    55  // Delete removes the revision of the specified manfiest.
    56  func (ms *manifestStore) Delete(dgst digest.Digest) error {
    57  	ctxu.GetLogger(ms.repository.ctx).Debug("(*manifestStore).Delete - unsupported")
    58  	return fmt.Errorf("deletion of manifests not supported")
    59  }
    60  
    61  func (ms *manifestStore) Tags() ([]string, error) {
    62  	ctxu.GetLogger(ms.repository.ctx).Debug("(*manifestStore).Tags")
    63  	return ms.tagStore.tags()
    64  }
    65  
    66  func (ms *manifestStore) ExistsByTag(tag string) (bool, error) {
    67  	ctxu.GetLogger(ms.repository.ctx).Debug("(*manifestStore).ExistsByTag")
    68  	return ms.tagStore.exists(tag)
    69  }
    70  
    71  func (ms *manifestStore) GetByTag(tag string) (*manifest.SignedManifest, error) {
    72  	ctxu.GetLogger(ms.repository.ctx).Debug("(*manifestStore).GetByTag")
    73  	dgst, err := ms.tagStore.resolve(tag)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  
    78  	return ms.revisionStore.get(dgst)
    79  }
    80  
    81  // verifyManifest ensures that the manifest content is valid from the
    82  // perspective of the registry. It ensures that the signature is valid for the
    83  // enclosed payload. As a policy, the registry only tries to store valid
    84  // content, leaving trust policies of that content up to consumers.
    85  func (ms *manifestStore) verifyManifest(mnfst *manifest.SignedManifest) error {
    86  	var errs distribution.ErrManifestVerification
    87  	if mnfst.Name != ms.repository.Name() {
    88  		// TODO(stevvooe): This needs to be an exported error
    89  		errs = append(errs, fmt.Errorf("repository name does not match manifest name"))
    90  	}
    91  
    92  	if _, err := manifest.Verify(mnfst); err != nil {
    93  		switch err {
    94  		case libtrust.ErrMissingSignatureKey, libtrust.ErrInvalidJSONContent, libtrust.ErrMissingSignatureKey:
    95  			errs = append(errs, distribution.ErrManifestUnverified{})
    96  		default:
    97  			if err.Error() == "invalid signature" { // TODO(stevvooe): This should be exported by libtrust
    98  				errs = append(errs, distribution.ErrManifestUnverified{})
    99  			} else {
   100  				errs = append(errs, err)
   101  			}
   102  		}
   103  	}
   104  
   105  	for _, fsLayer := range mnfst.FSLayers {
   106  		exists, err := ms.repository.Layers().Exists(fsLayer.BlobSum)
   107  		if err != nil {
   108  			errs = append(errs, err)
   109  		}
   110  
   111  		if !exists {
   112  			errs = append(errs, distribution.ErrUnknownLayer{FSLayer: fsLayer})
   113  		}
   114  	}
   115  
   116  	if len(errs) != 0 {
   117  		// TODO(stevvooe): These need to be recoverable by a caller.
   118  		return errs
   119  	}
   120  
   121  	return nil
   122  }