mirror of
https://github.com/project-zot/zot.git
synced 2026-06-16 20:38:08 +08:00
feat(sync): sync references(signatures/artifacts) recursively (#1500)
sync now also pulls chained artifacts recursively eg: image->sbom->sbom signature image->artifact->artifact Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>
This commit is contained in:
@@ -4,12 +4,12 @@
|
||||
package references
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
godigest "github.com/opencontainers/go-digest"
|
||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/sigstore/cosign/v2/pkg/oci/remote"
|
||||
|
||||
@@ -46,12 +46,12 @@ func (ref CosignReference) Name() string {
|
||||
|
||||
func (ref CosignReference) IsSigned(upstreamRepo, subjectDigestStr string) bool {
|
||||
cosignSignatureTag := getCosignSignatureTagFromSubjectDigest(subjectDigestStr)
|
||||
_, err := ref.getManifest(upstreamRepo, cosignSignatureTag)
|
||||
_, _, err := ref.getManifest(upstreamRepo, cosignSignatureTag)
|
||||
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (ref CosignReference) canSkipReferences(localRepo, cosignTag string, manifest *ispec.Manifest) (
|
||||
func (ref CosignReference) canSkipReferences(localRepo, digest string, manifest *ispec.Manifest) (
|
||||
bool, error,
|
||||
) {
|
||||
if manifest == nil {
|
||||
@@ -59,64 +59,57 @@ func (ref CosignReference) canSkipReferences(localRepo, cosignTag string, manife
|
||||
}
|
||||
|
||||
imageStore := ref.storeController.GetImageStore(localRepo)
|
||||
|
||||
// check cosign signature already synced
|
||||
|
||||
var localManifest ispec.Manifest
|
||||
|
||||
/* we need to use tag (cosign format: sha256-$IMAGE_TAG.sig) instead of digest to get local cosign manifest
|
||||
because of an issue where cosign digests differs between upstream and downstream */
|
||||
|
||||
localManifestBuf, _, _, err := imageStore.GetImageManifest(localRepo, cosignTag)
|
||||
_, localDigest, _, err := imageStore.GetImageManifest(localRepo, digest)
|
||||
if err != nil {
|
||||
if errors.Is(err, zerr.ErrManifestNotFound) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
ref.log.Error().Str("errorType", common.TypeOf(err)).Err(err).
|
||||
Str("repository", localRepo).Str("reference", cosignTag).
|
||||
Str("repository", localRepo).Str("reference", digest).
|
||||
Msg("couldn't get local cosign manifest")
|
||||
|
||||
return false, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(localManifestBuf, &localManifest)
|
||||
if err != nil {
|
||||
ref.log.Error().Str("errorType", common.TypeOf(err)).
|
||||
Str("repository", localRepo).Str("reference", cosignTag).
|
||||
Err(err).Msg("couldn't unmarshal local cosign signature manifest")
|
||||
|
||||
return false, err
|
||||
}
|
||||
|
||||
if !manifestsEqual(localManifest, *manifest) {
|
||||
ref.log.Info().Str("repository", localRepo).Str("reference", cosignTag).
|
||||
Msg("upstream cosign signatures changed, syncing again")
|
||||
|
||||
if localDigest.String() != digest {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
ref.log.Info().Str("repository", localRepo).Str("reference", cosignTag).
|
||||
Msg("skipping syncing cosign signature, already synced")
|
||||
ref.log.Info().Str("repository", localRepo).Str("reference", digest).
|
||||
Msg("skipping syncing cosign reference, already synced")
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (ref CosignReference) SyncReferences(localRepo, remoteRepo, subjectDigestStr string) error {
|
||||
func (ref CosignReference) SyncReferences(localRepo, remoteRepo, subjectDigestStr string) ([]godigest.Digest, error) {
|
||||
cosignTags := getCosignTagsFromSubjectDigest(subjectDigestStr)
|
||||
|
||||
refsDigests := make([]godigest.Digest, 0, len(cosignTags))
|
||||
|
||||
for _, cosignTag := range cosignTags {
|
||||
manifest, err := ref.getManifest(remoteRepo, cosignTag)
|
||||
if err != nil && errors.Is(err, zerr.ErrSyncReferrerNotFound) {
|
||||
return err
|
||||
manifest, manifestBuf, err := ref.getManifest(remoteRepo, cosignTag)
|
||||
if err != nil {
|
||||
if errors.Is(err, zerr.ErrSyncReferrerNotFound) {
|
||||
continue
|
||||
}
|
||||
|
||||
return refsDigests, err
|
||||
}
|
||||
|
||||
skip, err := ref.canSkipReferences(localRepo, cosignTag, manifest)
|
||||
digest := godigest.FromBytes(manifestBuf)
|
||||
|
||||
skip, err := ref.canSkipReferences(localRepo, digest.String(), manifest)
|
||||
if err != nil {
|
||||
ref.log.Error().Err(err).Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||
Msg("couldn't check if the remote image cosign reference can be skipped")
|
||||
}
|
||||
|
||||
if skip {
|
||||
refsDigests = append(refsDigests, digest)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -127,22 +120,13 @@ func (ref CosignReference) SyncReferences(localRepo, remoteRepo, subjectDigestSt
|
||||
|
||||
for _, blob := range manifest.Layers {
|
||||
if err := syncBlob(ref.client, imageStore, localRepo, remoteRepo, blob.Digest, ref.log); err != nil {
|
||||
return err
|
||||
return refsDigests, err
|
||||
}
|
||||
}
|
||||
|
||||
// sync config blob
|
||||
if err := syncBlob(ref.client, imageStore, localRepo, remoteRepo, manifest.Config.Digest, ref.log); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
manifestBuf, err := json.Marshal(manifest)
|
||||
if err != nil {
|
||||
ref.log.Error().Str("errorType", common.TypeOf(err)).
|
||||
Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||
Err(err).Msg("couldn't marshal cosign reference manifest")
|
||||
|
||||
return err
|
||||
return refsDigests, err
|
||||
}
|
||||
|
||||
// push manifest
|
||||
@@ -153,9 +137,11 @@ func (ref CosignReference) SyncReferences(localRepo, remoteRepo, subjectDigestSt
|
||||
Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||
Err(err).Msg("couldn't upload cosign reference manifest for image")
|
||||
|
||||
return err
|
||||
return refsDigests, err
|
||||
}
|
||||
|
||||
refsDigests = append(refsDigests, digest)
|
||||
|
||||
ref.log.Info().Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||
Msg("successfully synced cosign reference for image")
|
||||
|
||||
@@ -166,7 +152,7 @@ func (ref CosignReference) SyncReferences(localRepo, remoteRepo, subjectDigestSt
|
||||
isSig, sigType, signedManifestDig, err := storage.CheckIsImageSignature(localRepo, manifestBuf,
|
||||
cosignTag)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check if cosign reference '%s@%s' is a signature: %w", localRepo,
|
||||
return refsDigests, fmt.Errorf("failed to check if cosign reference '%s@%s' is a signature: %w", localRepo,
|
||||
cosignTag, err)
|
||||
}
|
||||
|
||||
@@ -176,13 +162,14 @@ func (ref CosignReference) SyncReferences(localRepo, remoteRepo, subjectDigestSt
|
||||
SignatureDigest: referenceDigest.String(),
|
||||
})
|
||||
} else {
|
||||
err = repodb.SetImageMetaFromInput(localRepo, cosignTag, manifest.MediaType,
|
||||
err = repodb.SetImageMetaFromInput(localRepo, cosignTag, ispec.MediaTypeImageManifest,
|
||||
referenceDigest, manifestBuf, ref.storeController.GetImageStore(localRepo),
|
||||
ref.repoDB, ref.log)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set metadata for cosign reference in '%s@%s': %w", localRepo, subjectDigestStr, err)
|
||||
return refsDigests, fmt.Errorf("failed to set metadata for cosign reference in '%s@%s': %w",
|
||||
localRepo, subjectDigestStr, err)
|
||||
}
|
||||
|
||||
ref.log.Info().Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||
@@ -190,13 +177,13 @@ func (ref CosignReference) SyncReferences(localRepo, remoteRepo, subjectDigestSt
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return refsDigests, nil
|
||||
}
|
||||
|
||||
func (ref CosignReference) getManifest(repo, cosignTag string) (*ispec.Manifest, error) {
|
||||
func (ref CosignReference) getManifest(repo, cosignTag string) (*ispec.Manifest, []byte, error) {
|
||||
var cosignManifest ispec.Manifest
|
||||
|
||||
_, _, statusCode, err := ref.client.MakeGetRequest(&cosignManifest, ispec.MediaTypeImageManifest,
|
||||
body, _, statusCode, err := ref.client.MakeGetRequest(&cosignManifest, ispec.MediaTypeImageManifest,
|
||||
"v2", repo, "manifests", cosignTag)
|
||||
if err != nil {
|
||||
if statusCode == http.StatusNotFound {
|
||||
@@ -204,17 +191,17 @@ func (ref CosignReference) getManifest(repo, cosignTag string) (*ispec.Manifest,
|
||||
Str("repository", repo).Str("tag", cosignTag).
|
||||
Err(err).Msg("couldn't find any cosign manifest for image")
|
||||
|
||||
return nil, zerr.ErrSyncReferrerNotFound
|
||||
return nil, nil, zerr.ErrSyncReferrerNotFound
|
||||
}
|
||||
|
||||
ref.log.Error().Str("errorType", common.TypeOf(err)).
|
||||
Str("repository", repo).Str("tag", cosignTag).Int("statusCode", statusCode).
|
||||
Err(err).Msg("couldn't get cosign manifest for image")
|
||||
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return &cosignManifest, nil
|
||||
return &cosignManifest, body, nil
|
||||
}
|
||||
|
||||
func getCosignSignatureTagFromSubjectDigest(digestStr string) string {
|
||||
|
||||
@@ -90,10 +90,12 @@ func (ref OciReferences) canSkipReferences(localRepo, subjectDigestStr string, i
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (ref OciReferences) SyncReferences(localRepo, remoteRepo, subjectDigestStr string) error {
|
||||
func (ref OciReferences) SyncReferences(localRepo, remoteRepo, subjectDigestStr string) ([]godigest.Digest, error) {
|
||||
refsDigests := make([]godigest.Digest, 0, 10)
|
||||
|
||||
index, err := ref.getIndex(remoteRepo, subjectDigestStr)
|
||||
if err != nil {
|
||||
return err
|
||||
return refsDigests, err
|
||||
}
|
||||
|
||||
skipOCIRefs, err := ref.canSkipReferences(localRepo, subjectDigestStr, index)
|
||||
@@ -103,7 +105,13 @@ func (ref OciReferences) SyncReferences(localRepo, remoteRepo, subjectDigestStr
|
||||
}
|
||||
|
||||
if skipOCIRefs {
|
||||
return nil
|
||||
/* even if it's skip we need to return the digests,
|
||||
because maybe in the meantime a reference pointing to this one was pushed */
|
||||
for _, man := range index.Manifests {
|
||||
refsDigests = append(refsDigests, man.Digest)
|
||||
}
|
||||
|
||||
return refsDigests, nil
|
||||
}
|
||||
|
||||
imageStore := ref.storeController.GetImageStore(localRepo)
|
||||
@@ -118,14 +126,14 @@ func (ref OciReferences) SyncReferences(localRepo, remoteRepo, subjectDigestStr
|
||||
"v2", remoteRepo, "manifests", referrer.Digest.String())
|
||||
if err != nil {
|
||||
if statusCode == http.StatusNotFound {
|
||||
return zerr.ErrSyncReferrerNotFound
|
||||
return refsDigests, zerr.ErrSyncReferrerNotFound
|
||||
}
|
||||
|
||||
ref.log.Error().Str("errorType", common.TypeOf(err)).
|
||||
Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||
Err(err).Msg("couldn't get oci reference manifest for image")
|
||||
|
||||
return err
|
||||
return refsDigests, err
|
||||
}
|
||||
|
||||
if referrer.MediaType == ispec.MediaTypeImageManifest {
|
||||
@@ -138,33 +146,35 @@ func (ref OciReferences) SyncReferences(localRepo, remoteRepo, subjectDigestStr
|
||||
Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||
Err(err).Msg("couldn't unmarshal oci reference manifest for image")
|
||||
|
||||
return err
|
||||
return refsDigests, err
|
||||
}
|
||||
|
||||
for _, layer := range manifest.Layers {
|
||||
if err := syncBlob(ref.client, imageStore, localRepo, remoteRepo, layer.Digest, ref.log); err != nil {
|
||||
return err
|
||||
return refsDigests, err
|
||||
}
|
||||
}
|
||||
|
||||
// sync config blob
|
||||
if err := syncBlob(ref.client, imageStore, localRepo, remoteRepo, manifest.Config.Digest, ref.log); err != nil {
|
||||
return err
|
||||
return refsDigests, err
|
||||
}
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
|
||||
digest, _, err := imageStore.PutImageManifest(localRepo, referrer.Digest.String(),
|
||||
referenceDigest, _, err := imageStore.PutImageManifest(localRepo, referrer.Digest.String(),
|
||||
referrer.MediaType, OCIRefBuf)
|
||||
if err != nil {
|
||||
ref.log.Error().Str("errorType", common.TypeOf(err)).
|
||||
Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||
Err(err).Msg("couldn't upload oci reference for image")
|
||||
|
||||
return err
|
||||
return refsDigests, err
|
||||
}
|
||||
|
||||
refsDigests = append(refsDigests, referenceDigest)
|
||||
|
||||
if ref.repoDB != nil {
|
||||
ref.log.Debug().Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||
Msg("repoDB: trying to add oci references for image")
|
||||
@@ -172,23 +182,24 @@ func (ref OciReferences) SyncReferences(localRepo, remoteRepo, subjectDigestStr
|
||||
isSig, sigType, signedManifestDig, err := storage.CheckIsImageSignature(localRepo, OCIRefBuf,
|
||||
referrer.Digest.String())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check if oci reference '%s@%s' is a signature: %w", localRepo,
|
||||
return refsDigests, fmt.Errorf("failed to check if oci reference '%s@%s' is a signature: %w", localRepo,
|
||||
referrer.Digest.String(), err)
|
||||
}
|
||||
|
||||
if isSig {
|
||||
err = ref.repoDB.AddManifestSignature(localRepo, signedManifestDig, repodb.SignatureMetadata{
|
||||
SignatureType: sigType,
|
||||
SignatureDigest: digest.String(),
|
||||
SignatureDigest: referenceDigest.String(),
|
||||
})
|
||||
} else {
|
||||
err = repodb.SetImageMetaFromInput(localRepo, digest.String(), referrer.MediaType,
|
||||
digest, OCIRefBuf, ref.storeController.GetImageStore(localRepo),
|
||||
err = repodb.SetImageMetaFromInput(localRepo, referenceDigest.String(), referrer.MediaType,
|
||||
referenceDigest, OCIRefBuf, ref.storeController.GetImageStore(localRepo),
|
||||
ref.repoDB, ref.log)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set metadata for oci reference in '%s@%s': %w", localRepo, subjectDigestStr, err)
|
||||
return refsDigests, fmt.Errorf("failed to set metadata for oci reference in '%s@%s': %w",
|
||||
localRepo, subjectDigestStr, err)
|
||||
}
|
||||
|
||||
ref.log.Info().Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||
@@ -199,7 +210,7 @@ func (ref OciReferences) SyncReferences(localRepo, remoteRepo, subjectDigestStr
|
||||
ref.log.Info().Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||
Msg("successfully synced oci references for image")
|
||||
|
||||
return nil
|
||||
return refsDigests, nil
|
||||
}
|
||||
|
||||
func (ref OciReferences) getIndex(repo, subjectDigestStr string) (ispec.Index, error) {
|
||||
|
||||
@@ -84,10 +84,12 @@ func (ref ORASReferences) canSkipReferences(localRepo, subjectDigestStr string,
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (ref ORASReferences) SyncReferences(localRepo, remoteRepo, subjectDigestStr string) error {
|
||||
func (ref ORASReferences) SyncReferences(localRepo, remoteRepo, subjectDigestStr string) ([]godigest.Digest, error) {
|
||||
refsDigests := make([]godigest.Digest, 0, 10)
|
||||
|
||||
referrers, err := ref.getReferenceList(remoteRepo, subjectDigestStr)
|
||||
if err != nil {
|
||||
return err
|
||||
return refsDigests, err
|
||||
}
|
||||
|
||||
skipORASRefs, err := ref.canSkipReferences(localRepo, subjectDigestStr, referrers)
|
||||
@@ -97,7 +99,11 @@ func (ref ORASReferences) SyncReferences(localRepo, remoteRepo, subjectDigestStr
|
||||
}
|
||||
|
||||
if skipORASRefs {
|
||||
return nil
|
||||
for _, man := range referrers.References {
|
||||
refsDigests = append(refsDigests, man.Digest)
|
||||
}
|
||||
|
||||
return refsDigests, nil
|
||||
}
|
||||
|
||||
imageStore := ref.storeController.GetImageStore(localRepo)
|
||||
@@ -112,41 +118,44 @@ func (ref ORASReferences) SyncReferences(localRepo, remoteRepo, subjectDigestStr
|
||||
"v2", remoteRepo, "manifests", referrer.Digest.String())
|
||||
if err != nil {
|
||||
if statusCode == http.StatusNotFound {
|
||||
return zerr.ErrSyncReferrerNotFound
|
||||
return refsDigests, zerr.ErrSyncReferrerNotFound
|
||||
}
|
||||
|
||||
ref.log.Error().Str("errorType", common.TypeOf(err)).
|
||||
Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||
Err(err).Msg("couldn't get ORAS artifact for image")
|
||||
|
||||
return err
|
||||
return refsDigests, err
|
||||
}
|
||||
|
||||
for _, blob := range artifactManifest.Blobs {
|
||||
if err := syncBlob(ref.client, imageStore, localRepo, remoteRepo, blob.Digest, ref.log); err != nil {
|
||||
return err
|
||||
return refsDigests, err
|
||||
}
|
||||
}
|
||||
|
||||
digest, _, err := imageStore.PutImageManifest(localRepo, referrer.Digest.String(),
|
||||
referenceDigest, _, err := imageStore.PutImageManifest(localRepo, referrer.Digest.String(),
|
||||
oras.MediaTypeArtifactManifest, orasBuf)
|
||||
if err != nil {
|
||||
ref.log.Error().Str("errorType", common.TypeOf(err)).
|
||||
Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||
Err(err).Msg("couldn't upload ORAS artifact for image")
|
||||
|
||||
return err
|
||||
return refsDigests, err
|
||||
}
|
||||
|
||||
refsDigests = append(refsDigests, referenceDigest)
|
||||
|
||||
if ref.repoDB != nil {
|
||||
ref.log.Debug().Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||
Msg("repoDB: trying to sync oras artifact for image")
|
||||
|
||||
err := repodb.SetImageMetaFromInput(localRepo, digest.String(), referrer.MediaType,
|
||||
digest, orasBuf, ref.storeController.GetImageStore(localRepo),
|
||||
err := repodb.SetImageMetaFromInput(localRepo, referenceDigest.String(), referrer.MediaType,
|
||||
referenceDigest, orasBuf, ref.storeController.GetImageStore(localRepo),
|
||||
ref.repoDB, ref.log)
|
||||
if err != nil {
|
||||
return fmt.Errorf("repoDB: failed to set metadata for oras artifact '%s@%s': %w", localRepo, subjectDigestStr, err)
|
||||
return refsDigests, fmt.Errorf("repoDB: failed to set metadata for oras artifact '%s@%s': %w",
|
||||
localRepo, subjectDigestStr, err)
|
||||
}
|
||||
|
||||
ref.log.Info().Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||
@@ -157,7 +166,7 @@ func (ref ORASReferences) SyncReferences(localRepo, remoteRepo, subjectDigestStr
|
||||
ref.log.Info().Str("repository", localRepo).Str("subject", subjectDigestStr).
|
||||
Msg("successfully synced oras artifacts for image")
|
||||
|
||||
return nil
|
||||
return refsDigests, nil
|
||||
}
|
||||
|
||||
func (ref ORASReferences) getReferenceList(repo, subjectDigestStr string) (ReferenceList, error) {
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
notreg "github.com/notaryproject/notation-go/registry"
|
||||
"github.com/opencontainers/go-digest"
|
||||
godigest "github.com/opencontainers/go-digest"
|
||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
artifactspec "github.com/oras-project/artifacts-spec/specs-go/v1"
|
||||
"github.com/sigstore/cosign/v2/pkg/oci/static"
|
||||
@@ -23,14 +23,17 @@ import (
|
||||
)
|
||||
|
||||
type Reference interface {
|
||||
// Returns name of reference (OCIReference/CosignReference/OrasReference)
|
||||
Name() string
|
||||
// Returns whether or not image is signed
|
||||
IsSigned(upstreamRepo, subjectDigestStr string) bool
|
||||
SyncReferences(localRepo, upstreamRepo, subjectDigestStr string) error
|
||||
// Sync recursively all references for a subject digest (can be image/artifacts/signatures)
|
||||
SyncReferences(localRepo, upstreamRepo, subjectDigestStr string) ([]godigest.Digest, error)
|
||||
}
|
||||
|
||||
type References struct {
|
||||
refernceList []Reference
|
||||
log log.Logger
|
||||
referenceList []Reference
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func NewReferences(httpClient *client.Client, storeController storage.StoreController,
|
||||
@@ -38,15 +41,15 @@ func NewReferences(httpClient *client.Client, storeController storage.StoreContr
|
||||
) References {
|
||||
refs := References{log: log}
|
||||
|
||||
refs.refernceList = append(refs.refernceList, NewCosignReference(httpClient, storeController, repoDB, log))
|
||||
refs.refernceList = append(refs.refernceList, NewOciReferences(httpClient, storeController, repoDB, log))
|
||||
refs.refernceList = append(refs.refernceList, NewORASReferences(httpClient, storeController, repoDB, log))
|
||||
refs.referenceList = append(refs.referenceList, NewCosignReference(httpClient, storeController, repoDB, log))
|
||||
refs.referenceList = append(refs.referenceList, NewOciReferences(httpClient, storeController, repoDB, log))
|
||||
refs.referenceList = append(refs.referenceList, NewORASReferences(httpClient, storeController, repoDB, log))
|
||||
|
||||
return refs
|
||||
}
|
||||
|
||||
func (refs References) IsSigned(upstreamRepo, subjectDigestStr string) bool {
|
||||
for _, ref := range refs.refernceList {
|
||||
for _, ref := range refs.referenceList {
|
||||
ok := ref.IsSigned(upstreamRepo, subjectDigestStr)
|
||||
if ok {
|
||||
return true
|
||||
@@ -57,25 +60,50 @@ func (refs References) IsSigned(upstreamRepo, subjectDigestStr string) bool {
|
||||
}
|
||||
|
||||
func (refs References) SyncAll(localRepo, upstreamRepo, subjectDigestStr string) error {
|
||||
seen := &[]godigest.Digest{}
|
||||
|
||||
return refs.syncAll(localRepo, upstreamRepo, subjectDigestStr, seen)
|
||||
}
|
||||
|
||||
func (refs References) syncAll(localRepo, upstreamRepo, subjectDigestStr string, seen *[]godigest.Digest) error {
|
||||
var err error
|
||||
|
||||
for _, ref := range refs.refernceList {
|
||||
err = ref.SyncReferences(localRepo, upstreamRepo, subjectDigestStr)
|
||||
var syncedRefsDigests []godigest.Digest
|
||||
|
||||
// mark subject digest as seen as soon as it comes in
|
||||
*seen = append(*seen, godigest.Digest(subjectDigestStr))
|
||||
|
||||
// for each reference type(cosign/oci/oras reference)
|
||||
for _, ref := range refs.referenceList {
|
||||
syncedRefsDigests, err = ref.SyncReferences(localRepo, upstreamRepo, subjectDigestStr)
|
||||
if err != nil {
|
||||
refs.log.Error().Err(err).
|
||||
refs.log.Debug().Err(err).
|
||||
Str("reference type", ref.Name()).
|
||||
Str("image", fmt.Sprintf("%s:%s", upstreamRepo, subjectDigestStr)).
|
||||
Msg("couldn't sync image referrer")
|
||||
}
|
||||
|
||||
// for each synced references
|
||||
for _, refDigest := range syncedRefsDigests {
|
||||
if !common.Contains(*seen, refDigest) {
|
||||
// sync all references pointing to this one
|
||||
err = refs.syncAll(localRepo, upstreamRepo, refDigest.String(), seen)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (refs References) SyncReference(localRepo, upstreamRepo, subjectDigestStr, referenceType string) error {
|
||||
for _, ref := range refs.refernceList {
|
||||
var err error
|
||||
|
||||
var syncedRefsDigests []godigest.Digest
|
||||
|
||||
for _, ref := range refs.referenceList {
|
||||
if ref.Name() == referenceType {
|
||||
if err := ref.SyncReferences(localRepo, upstreamRepo, subjectDigestStr); err != nil {
|
||||
syncedRefsDigests, err = ref.SyncReferences(localRepo, upstreamRepo, subjectDigestStr)
|
||||
if err != nil {
|
||||
refs.log.Error().Err(err).
|
||||
Str("reference type", ref.Name()).
|
||||
Str("image", fmt.Sprintf("%s:%s", upstreamRepo, subjectDigestStr)).
|
||||
@@ -83,14 +111,18 @@ func (refs References) SyncReference(localRepo, upstreamRepo, subjectDigestStr,
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
for _, refDigest := range syncedRefsDigests {
|
||||
err = refs.SyncAll(localRepo, upstreamRepo, refDigest.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
func syncBlob(client *client.Client, imageStore storageTypes.ImageStore, localRepo, remoteRepo string,
|
||||
digest digest.Digest, log log.Logger,
|
||||
digest godigest.Digest, log log.Logger,
|
||||
) error {
|
||||
var resultPtr interface{}
|
||||
|
||||
|
||||
@@ -48,13 +48,13 @@ func TestCosign(t *testing.T) {
|
||||
|
||||
cosign = NewCosignReference(client, storage.StoreController{DefaultStore: mocks.MockedImageStore{
|
||||
GetImageManifestFn: func(repo, reference string) ([]byte, godigest.Digest, string, error) {
|
||||
return []byte{}, "", "", nil
|
||||
return []byte{}, "digest", "", nil
|
||||
},
|
||||
}}, nil, log.NewLogger("debug", ""))
|
||||
|
||||
// trigger unmarshal err
|
||||
// different digest
|
||||
ok, err = cosign.canSkipReferences("repo", "tag", &ispec.Manifest{MediaType: ispec.MediaTypeImageManifest})
|
||||
So(err, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(ok, ShouldBeFalse)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user