feat(graphql & repodb): add info about signature validity (#1344)

Signed-off-by: Andreea-Lupu <andreealupu1470@yahoo.com>
This commit is contained in:
Andreea Lupu
2023-05-24 19:46:16 +03:00
committed by GitHub
parent 6e6ffe800c
commit 970997f3a8
24 changed files with 2053 additions and 31 deletions
@@ -17,6 +17,7 @@ import (
"zotregistry.io/zot/pkg/meta/bolt"
"zotregistry.io/zot/pkg/meta/common"
"zotregistry.io/zot/pkg/meta/repodb"
"zotregistry.io/zot/pkg/meta/signatures"
"zotregistry.io/zot/pkg/meta/version"
localCtx "zotregistry.io/zot/pkg/requestcontext"
)
@@ -726,6 +727,102 @@ func (bdw *DBWrapper) IncrementImageDownloads(repo string, reference string) err
return err
}
func (bdw *DBWrapper) UpdateSignaturesValidity(repo string, manifestDigest godigest.Digest) error {
err := bdw.DB.Update(func(transaction *bbolt.Tx) error {
// get ManifestData of signed manifest
manifestBuck := transaction.Bucket([]byte(bolt.ManifestDataBucket))
mdBlob := manifestBuck.Get([]byte(manifestDigest))
var blob []byte
if len(mdBlob) != 0 {
var manifestData repodb.ManifestData
err := json.Unmarshal(mdBlob, &manifestData)
if err != nil {
return fmt.Errorf("repodb: %w error while unmashaling manifest meta for digest %s", err, manifestDigest)
}
blob = manifestData.ManifestBlob
} else {
var indexData repodb.IndexData
indexBuck := transaction.Bucket([]byte(bolt.IndexDataBucket))
idBlob := indexBuck.Get([]byte(manifestDigest))
if len(idBlob) == 0 {
// manifest meta not found, updating signatures with details about validity and author will not be performed
return nil
}
err := json.Unmarshal(idBlob, &indexData)
if err != nil {
return fmt.Errorf("repodb: %w error while unmashaling index meta for digest %s", err, manifestDigest)
}
blob = indexData.IndexBlob
}
// update signatures with details about validity and author
repoBuck := transaction.Bucket([]byte(bolt.RepoMetadataBucket))
repoMetaBlob := repoBuck.Get([]byte(repo))
if repoMetaBlob == nil {
return zerr.ErrRepoMetaNotFound
}
var repoMeta repodb.RepoMetadata
err := json.Unmarshal(repoMetaBlob, &repoMeta)
if err != nil {
return err
}
manifestSignatures := repodb.ManifestSignatures{}
for sigType, sigs := range repoMeta.Signatures[manifestDigest.String()] {
signaturesInfo := []repodb.SignatureInfo{}
for _, sigInfo := range sigs {
layersInfo := []repodb.LayerInfo{}
for _, layerInfo := range sigInfo.LayersInfo {
author, date, isTrusted, _ := signatures.VerifySignature(sigType, layerInfo.LayerContent, layerInfo.SignatureKey,
manifestDigest, blob, repo)
if isTrusted {
layerInfo.Signer = author
}
if !date.IsZero() {
layerInfo.Signer = author
layerInfo.Date = date
}
layersInfo = append(layersInfo, layerInfo)
}
signaturesInfo = append(signaturesInfo, repodb.SignatureInfo{
SignatureManifestDigest: sigInfo.SignatureManifestDigest,
LayersInfo: layersInfo,
})
}
manifestSignatures[sigType] = signaturesInfo
}
repoMeta.Signatures[manifestDigest.String()] = manifestSignatures
repoMetaBlob, err = json.Marshal(repoMeta)
if err != nil {
return err
}
return repoBuck.Put([]byte(repo), repoMetaBlob)
})
return err
}
func (bdw *DBWrapper) AddManifestSignature(repo string, signedManifestDigest godigest.Digest,
sygMeta repodb.SignatureMetadata,
) error {
@@ -780,10 +877,17 @@ func (bdw *DBWrapper) AddManifestSignature(repo string, signedManifestDigest god
signatureSlice := manifestSignatures[sygMeta.SignatureType]
if !common.SignatureAlreadyExists(signatureSlice, sygMeta) {
signatureSlice = append(signatureSlice, repodb.SignatureInfo{
SignatureManifestDigest: sygMeta.SignatureDigest,
LayersInfo: sygMeta.LayersInfo,
})
if sygMeta.SignatureType == signatures.NotationSignature {
signatureSlice = append(signatureSlice, repodb.SignatureInfo{
SignatureManifestDigest: sygMeta.SignatureDigest,
LayersInfo: sygMeta.LayersInfo,
})
} else if sygMeta.SignatureType == signatures.CosignSignature {
signatureSlice = []repodb.SignatureInfo{{
SignatureManifestDigest: sygMeta.SignatureDigest,
LayersInfo: sygMeta.LayersInfo,
}}
}
}
manifestSignatures[sygMeta.SignatureType] = signatureSlice
@@ -3,8 +3,15 @@ package bolt_test
import (
"context"
"encoding/json"
"errors"
"os"
"path"
"testing"
"time"
"github.com/notaryproject/notation-core-go/signature/jws"
"github.com/notaryproject/notation-go"
"github.com/notaryproject/notation-go/signer"
"github.com/opencontainers/go-digest"
ispec "github.com/opencontainers/image-spec/specs-go/v1"
. "github.com/smartystreets/goconvey/convey"
@@ -14,6 +21,7 @@ import (
"zotregistry.io/zot/pkg/meta/bolt"
"zotregistry.io/zot/pkg/meta/repodb"
boltdb_wrapper "zotregistry.io/zot/pkg/meta/repodb/boltdb-wrapper"
"zotregistry.io/zot/pkg/meta/signatures"
localCtx "zotregistry.io/zot/pkg/requestcontext"
"zotregistry.io/zot/pkg/test"
)
@@ -308,6 +316,20 @@ func TestWrapperErrors(t *testing.T) {
})
So(err, ShouldBeNil)
err = boltdbWrapper.AddManifestSignature("repo1", digest.FromString("dig"),
repodb.SignatureMetadata{
SignatureType: "cosign",
SignatureDigest: "digest2",
})
So(err, ShouldBeNil)
repoData, err := boltdbWrapper.GetRepoMeta("repo1")
So(err, ShouldBeNil)
So(len(repoData.Signatures[string(digest.FromString("dig"))][signatures.CosignSignature]),
ShouldEqual, 1)
So(repoData.Signatures[string(digest.FromString("dig"))][signatures.CosignSignature][0].SignatureManifestDigest,
ShouldEqual, "digest2")
err = boltdbWrapper.AddManifestSignature("repo1", digest.FromString("dig"),
repodb.SignatureMetadata{
SignatureType: "notation",
@@ -930,6 +952,231 @@ func TestWrapperErrors(t *testing.T) {
_, err := boltdbWrapper.GetUserRepoMeta(ctx, "repo")
So(err, ShouldNotBeNil)
})
Convey("UpdateSignaturesValidity", func() {
Convey("manifestMeta of signed manifest not found", func() {
err := boltdbWrapper.UpdateSignaturesValidity("repo", digest.FromString("dig"))
So(err, ShouldBeNil)
})
Convey("repoMeta of signed manifest not found", func() {
// repo Meta not found
err := boltdbWrapper.SetManifestData(digest.FromString("dig"), repodb.ManifestData{
ManifestBlob: []byte("Bad Manifest"),
ConfigBlob: []byte("Bad Manifest"),
})
So(err, ShouldBeNil)
err = boltdbWrapper.UpdateSignaturesValidity("repo", digest.FromString("dig"))
So(err, ShouldNotBeNil)
})
Convey("manifest - bad content", func() {
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
dataBuck := tx.Bucket([]byte(bolt.ManifestDataBucket))
return dataBuck.Put([]byte("digest1"), []byte("wrong json"))
})
So(err, ShouldBeNil)
err = boltdbWrapper.UpdateSignaturesValidity("repo1", "digest1")
So(err, ShouldNotBeNil)
})
Convey("index - bad content", func() {
err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
dataBuck := tx.Bucket([]byte(bolt.IndexDataBucket))
return dataBuck.Put([]byte("digest1"), []byte("wrong json"))
})
So(err, ShouldBeNil)
err = boltdbWrapper.UpdateSignaturesValidity("repo1", "digest1")
So(err, ShouldNotBeNil)
})
Convey("repo - bad content", func() {
// repo Meta not found
err := boltdbWrapper.SetManifestData(digest.FromString("dig"), repodb.ManifestData{
ManifestBlob: []byte("Bad Manifest"),
ConfigBlob: []byte("Bad Manifest"),
})
So(err, ShouldBeNil)
err = boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
repoBuck := tx.Bucket([]byte(bolt.RepoMetadataBucket))
return repoBuck.Put([]byte("repo1"), []byte("wrong json"))
})
So(err, ShouldBeNil)
err = boltdbWrapper.UpdateSignaturesValidity("repo1", digest.FromString("dig"))
So(err, ShouldNotBeNil)
})
Convey("VerifySignature -> untrusted signature", func() {
err := boltdbWrapper.SetManifestData(digest.FromString("dig"), repodb.ManifestData{
ManifestBlob: []byte("Bad Manifest"),
ConfigBlob: []byte("Bad Manifest"),
})
So(err, ShouldBeNil)
err = boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
repoBuck := tx.Bucket([]byte(bolt.RepoMetadataBucket))
return repoBuck.Put([]byte("repo1"), repoMetaBlob)
})
So(err, ShouldBeNil)
layerInfo := repodb.LayerInfo{LayerDigest: "", LayerContent: []byte{}, SignatureKey: ""}
err = boltdbWrapper.AddManifestSignature("repo1", digest.FromString("dig"),
repodb.SignatureMetadata{
SignatureType: signatures.CosignSignature,
SignatureDigest: string(digest.FromString("signature digest")),
LayersInfo: []repodb.LayerInfo{layerInfo},
})
So(err, ShouldBeNil)
err = boltdbWrapper.UpdateSignaturesValidity("repo1", digest.FromString("dig"))
So(err, ShouldBeNil)
repoData, err := boltdbWrapper.GetRepoMeta("repo1")
So(err, ShouldBeNil)
So(repoData.Signatures[string(digest.FromString("dig"))][signatures.CosignSignature][0].LayersInfo[0].Signer,
ShouldBeEmpty)
So(repoData.Signatures[string(digest.FromString("dig"))][signatures.CosignSignature][0].LayersInfo[0].Date,
ShouldBeZeroValue)
})
Convey("VerifySignature -> trusted signature", func() {
_, _, manifest, _ := test.GetRandomImageComponents(10)
manifestContent, _ := json.Marshal(manifest)
manifestDigest := digest.FromBytes(manifestContent)
err := boltdbWrapper.SetManifestData(manifestDigest, repodb.ManifestData{
ManifestBlob: manifestContent,
ConfigBlob: []byte("configContent"),
})
So(err, ShouldBeNil)
err = boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error {
repoBuck := tx.Bucket([]byte(bolt.RepoMetadataBucket))
return repoBuck.Put([]byte("repo"), repoMetaBlob)
})
So(err, ShouldBeNil)
mediaType := jws.MediaTypeEnvelope
signOpts := notation.SignerSignOptions{
SignatureMediaType: mediaType,
PluginConfig: map[string]string{},
ExpiryDuration: 24 * time.Hour,
}
tdir := t.TempDir()
keyName := "notation-sign-test"
test.NotationPathLock.Lock()
defer test.NotationPathLock.Unlock()
test.LoadNotationPath(tdir)
err = test.GenerateNotationCerts(tdir, keyName)
So(err, ShouldBeNil)
// getSigner
var newSigner notation.Signer
// ResolveKey
signingKeys, err := test.LoadNotationSigningkeys(tdir)
So(err, ShouldBeNil)
idx := test.Index(signingKeys.Keys, keyName)
So(idx, ShouldBeGreaterThanOrEqualTo, 0)
key := signingKeys.Keys[idx]
if key.X509KeyPair != nil {
newSigner, err = signer.NewFromFiles(key.X509KeyPair.KeyPath, key.X509KeyPair.CertificatePath)
So(err, ShouldBeNil)
}
descToSign := ispec.Descriptor{
MediaType: manifest.MediaType,
Digest: manifestDigest,
Size: int64(len(manifestContent)),
}
sig, _, err := newSigner.Sign(ctx, descToSign, signOpts)
So(err, ShouldBeNil)
layerInfo := repodb.LayerInfo{
LayerDigest: string(digest.FromBytes(sig)),
LayerContent: sig, SignatureKey: mediaType,
}
err = boltdbWrapper.AddManifestSignature("repo", manifestDigest,
repodb.SignatureMetadata{
SignatureType: signatures.NotationSignature,
SignatureDigest: string(digest.FromString("signature digest")),
LayersInfo: []repodb.LayerInfo{layerInfo},
})
So(err, ShouldBeNil)
err = signatures.InitNotationDir(tdir)
So(err, ShouldBeNil)
trustpolicyPath := path.Join(tdir, "_notation/trustpolicy.json")
if _, err := os.Stat(trustpolicyPath); errors.Is(err, os.ErrNotExist) {
trustPolicy := `
{
"version": "1.0",
"trustPolicies": [
{
"name": "notation-sign-test",
"registryScopes": [ "*" ],
"signatureVerification": {
"level" : "strict"
},
"trustStores": ["ca:notation-sign-test"],
"trustedIdentities": [
"*"
]
}
]
}`
file, err := os.Create(trustpolicyPath)
So(err, ShouldBeNil)
defer file.Close()
_, err = file.WriteString(trustPolicy)
So(err, ShouldBeNil)
}
truststore := "_notation/truststore/x509/ca/notation-sign-test"
truststoreSrc := "notation/truststore/x509/ca/notation-sign-test"
err = os.MkdirAll(path.Join(tdir, truststore), 0o755)
So(err, ShouldBeNil)
err = test.CopyFile(path.Join(tdir, truststoreSrc, "notation-sign-test.crt"),
path.Join(tdir, truststore, "notation-sign-test.crt"))
So(err, ShouldBeNil)
err = boltdbWrapper.UpdateSignaturesValidity("repo", manifestDigest) //nolint:contextcheck
So(err, ShouldBeNil)
repoData, err := boltdbWrapper.GetRepoMeta("repo")
So(err, ShouldBeNil)
So(repoData.Signatures[string(manifestDigest)][signatures.NotationSignature][0].LayersInfo[0].Signer,
ShouldNotBeEmpty)
So(repoData.Signatures[string(manifestDigest)][signatures.NotationSignature][0].LayersInfo[0].Date,
ShouldNotBeZeroValue)
})
})
})
}
@@ -21,6 +21,7 @@ import (
"zotregistry.io/zot/pkg/meta/common"
"zotregistry.io/zot/pkg/meta/dynamo"
"zotregistry.io/zot/pkg/meta/repodb" //nolint:go-staticcheck
"zotregistry.io/zot/pkg/meta/signatures"
"zotregistry.io/zot/pkg/meta/version"
localCtx "zotregistry.io/zot/pkg/requestcontext"
)
@@ -616,6 +617,10 @@ func (dwr *DBWrapper) IncrementImageDownloads(repo string, reference string) err
return dwr.SetRepoMeta(repo, repoMeta)
}
func (dwr *DBWrapper) UpdateSignaturesValidity(repo string, manifestDigest godigest.Digest) error {
return nil
}
func (dwr *DBWrapper) AddManifestSignature(repo string, signedManifestDigest godigest.Digest,
sygMeta repodb.SignatureMetadata,
) error {
@@ -656,10 +661,17 @@ func (dwr *DBWrapper) AddManifestSignature(repo string, signedManifestDigest god
signatureSlice := manifestSignatures[sygMeta.SignatureType]
if !common.SignatureAlreadyExists(signatureSlice, sygMeta) {
signatureSlice = append(signatureSlice, repodb.SignatureInfo{
SignatureManifestDigest: sygMeta.SignatureDigest,
LayersInfo: sygMeta.LayersInfo,
})
if sygMeta.SignatureType == signatures.NotationSignature {
signatureSlice = append(signatureSlice, repodb.SignatureInfo{
SignatureManifestDigest: sygMeta.SignatureDigest,
LayersInfo: sygMeta.LayersInfo,
})
} else if sygMeta.SignatureType == signatures.CosignSignature {
signatureSlice = []repodb.SignatureInfo{{
SignatureManifestDigest: sygMeta.SignatureDigest,
LayersInfo: sygMeta.LayersInfo,
}}
}
}
manifestSignatures[sygMeta.SignatureType] = signatureSlice
+4 -7
View File
@@ -7,13 +7,6 @@ import (
godigest "github.com/opencontainers/go-digest"
)
const (
SignaturesDirPath = "/tmp/zot/signatures"
SigKey = "dev.cosignproject.cosign/signature"
NotationType = "notation"
CosignType = "cosign"
)
// Used to model changes to an object after a call to the DB.
type ToggleState int
@@ -97,6 +90,9 @@ type RepoDB interface { //nolint:interfacebloat
// DeleteSignature delets signature metadata to a given manifest from the database
DeleteSignature(repo string, signedManifestDigest godigest.Digest, sm SignatureMetadata) error
// UpdateSignaturesValidity checks and updates signatures validity of a given manifest
UpdateSignaturesValidity(repo string, manifestDigest godigest.Digest) error
// SearchRepos searches for repos given a search string
SearchRepos(ctx context.Context, searchText string, filter Filter, requestedPage PageInput) (
[]RepoMetadata, map[string]ManifestMetadata, map[string]IndexData, PageInfo, error)
@@ -183,6 +179,7 @@ type LayerInfo struct {
LayerContent []byte
SignatureKey string
Signer string
Date time.Time
}
type SignatureInfo struct {
@@ -12,6 +12,7 @@ import (
"zotregistry.io/zot/pkg/meta/repodb"
boltdb_wrapper "zotregistry.io/zot/pkg/meta/repodb/boltdb-wrapper"
dynamodb_wrapper "zotregistry.io/zot/pkg/meta/repodb/dynamodb-wrapper"
"zotregistry.io/zot/pkg/meta/signatures"
)
func New(storageConfig config.StorageConfig, log log.Logger) (repodb.RepoDB, error) {
@@ -34,6 +35,11 @@ func New(storageConfig config.StorageConfig, log log.Logger) (repodb.RepoDB, err
return nil, err
}
err = signatures.InitCosignAndNotationDirs(params.RootDir)
if err != nil {
return nil, err
}
return Create("boltdb", driver, params, log) //nolint:contextcheck
}
@@ -2,11 +2,13 @@ package repodbfactory_test
import (
"os"
"path"
"testing"
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
. "github.com/smartystreets/goconvey/convey"
"zotregistry.io/zot/pkg/api/config"
"zotregistry.io/zot/pkg/log"
"zotregistry.io/zot/pkg/meta/bolt"
"zotregistry.io/zot/pkg/meta/dynamo"
@@ -73,6 +75,31 @@ func TestCreateBoltDB(t *testing.T) {
})
}
func TestNew(t *testing.T) {
Convey("InitCosignAndNotationDirs fails", t, func() {
rootDir := t.TempDir()
var storageConfig config.StorageConfig
storageConfig.RootDirectory = rootDir
storageConfig.RemoteCache = false
log := log.NewLogger("debug", "")
_, err := os.Create(path.Join(rootDir, "repo.db"))
So(err, ShouldBeNil)
err = os.Chmod(rootDir, 0o555)
So(err, ShouldBeNil)
newRepodb, err := repodbfactory.New(storageConfig, log)
So(newRepodb, ShouldBeNil)
So(err, ShouldNotBeNil)
err = os.Chmod(rootDir, 0o777)
So(err, ShouldBeNil)
})
}
func skipDynamo(t *testing.T) {
t.Helper()
+110 -2
View File
@@ -11,6 +11,7 @@ import (
zerr "zotregistry.io/zot/errors"
zcommon "zotregistry.io/zot/pkg/common"
"zotregistry.io/zot/pkg/log"
"zotregistry.io/zot/pkg/meta/signatures"
"zotregistry.io/zot/pkg/storage"
)
@@ -105,15 +106,30 @@ func ParseRepo(repo string, repoDB RepoDB, storeController storage.StoreControll
}
if isSignature {
err := repoDB.AddManifestSignature(repo, signedManifestDigest,
layers, err := GetSignatureLayersInfo(repo, tag, manifest.Digest.String(), signatureType, manifestBlob,
imageStore, log)
if err != nil {
return err
}
err = repoDB.AddManifestSignature(repo, signedManifestDigest,
SignatureMetadata{
SignatureType: signatureType,
SignatureDigest: digest.String(),
LayersInfo: layers,
})
if err != nil {
log.Error().Err(err).Str("repository", repo).Str("tag", tag).
Str("manifestDigest", signedManifestDigest.String()).
Msg("load-repo: failed set signature meta for signed image manifest digest")
Msg("load-repo: failed set signature meta for signed image")
return err
}
err = repoDB.UpdateSignaturesValidity(repo, signedManifestDigest)
if err != nil {
log.Error().Err(err).Str("repository", repo).Str("reference", tag).Str("digest", signedManifestDigest.String()).Msg(
"load-repo: failed verify signatures validity for signed image")
return err
}
@@ -199,6 +215,98 @@ func isManifestMetaPresent(repo string, manifest ispec.Descriptor, repoDB RepoDB
return true, nil
}
func GetSignatureLayersInfo(
repo, tag, manifestDigest, signatureType string, manifestBlob []byte, imageStore storage.ImageStore, log log.Logger,
) ([]LayerInfo, error) {
switch signatureType {
case signatures.CosignSignature:
return getCosignSignatureLayersInfo(repo, tag, manifestDigest, manifestBlob, imageStore, log)
case signatures.NotationSignature:
return getNotationSignatureLayersInfo(repo, manifestDigest, manifestBlob, imageStore, log)
default:
return []LayerInfo{}, nil
}
}
func getCosignSignatureLayersInfo(
repo, tag, manifestDigest string, manifestBlob []byte, imageStore storage.ImageStore, log log.Logger,
) ([]LayerInfo, error) {
layers := []LayerInfo{}
var manifestContent ispec.Manifest
if err := json.Unmarshal(manifestBlob, &manifestContent); err != nil {
log.Error().Err(err).Str("repository", repo).Str("reference", tag).Str("digest", manifestDigest).Msg(
"load-repo: unable to marshal blob index")
return layers, err
}
for _, layer := range manifestContent.Layers {
layerContent, err := imageStore.GetBlobContent(repo, layer.Digest)
if err != nil {
log.Error().Err(err).Str("repository", repo).Str("reference", tag).Str("layerDigest", layer.Digest.String()).Msg(
"load-repo: unable to get cosign signature layer content")
return layers, err
}
layerSigKey, ok := layer.Annotations[signatures.CosignSigKey]
if !ok {
log.Error().Err(err).Str("repository", repo).Str("reference", tag).Str("layerDigest", layer.Digest.String()).Msg(
"load-repo: unable to get specific annotation of cosign signature")
}
layers = append(layers, LayerInfo{
LayerDigest: layer.Digest.String(),
LayerContent: layerContent,
SignatureKey: layerSigKey,
})
}
return layers, nil
}
func getNotationSignatureLayersInfo(
repo, manifestDigest string, manifestBlob []byte, imageStore storage.ImageStore, log log.Logger,
) ([]LayerInfo, error) {
layers := []LayerInfo{}
var manifestContent ispec.Manifest
if err := json.Unmarshal(manifestBlob, &manifestContent); err != nil {
log.Error().Err(err).Str("repository", repo).Str("reference", manifestDigest).Msg(
"load-repo: unable to marshal blob index")
return layers, err
}
if len(manifestContent.Layers) != 1 {
log.Error().Err(zerr.ErrBadManifest).Str("repository", repo).Str("reference", manifestDigest).
Msg("load-repo: notation signature manifest requires exactly one layer but it does not")
return layers, zerr.ErrBadManifest
}
layer := manifestContent.Layers[0].Digest
layerContent, err := imageStore.GetBlobContent(repo, layer)
if err != nil {
log.Error().Err(err).Str("repository", repo).Str("reference", manifestDigest).Str("layerDigest", layer.String()).Msg(
"load-repo: unable to get notation signature blob content")
return layers, err
}
layerSigKey := manifestContent.Layers[0].MediaType
layers = append(layers, LayerInfo{
LayerDigest: layer.String(),
LayerContent: layerContent,
SignatureKey: layerSigKey,
})
return layers, nil
}
// NewManifestMeta takes raw data about an image and createa a new ManifestMetadate object.
func NewManifestData(repoName string, manifestBlob []byte, imageStore storage.ImageStore,
) (ManifestData, error) {
+115
View File
@@ -22,6 +22,7 @@ import (
"zotregistry.io/zot/pkg/meta/repodb"
bolt_wrapper "zotregistry.io/zot/pkg/meta/repodb/boltdb-wrapper"
dynamo_wrapper "zotregistry.io/zot/pkg/meta/repodb/dynamodb-wrapper"
"zotregistry.io/zot/pkg/meta/signatures"
"zotregistry.io/zot/pkg/storage"
"zotregistry.io/zot/pkg/storage/local"
"zotregistry.io/zot/pkg/test"
@@ -242,6 +243,7 @@ func TestParseStorageErrors(t *testing.T) {
Digest: "123",
},
ArtifactType: "application/vnd.cncf.notary.signature",
Layers: []ispec.Descriptor{{MediaType: ispec.MediaTypeImageLayer}},
}
manifestBlob, err := json.Marshal(manifestContent)
@@ -259,6 +261,100 @@ func TestParseStorageErrors(t *testing.T) {
err = repodb.ParseRepo("repo", repoDB, storeController, log)
So(err, ShouldNotBeNil)
repoDB.AddManifestSignatureFn = func(repo string, signedManifestDigest godigest.Digest,
sm repodb.SignatureMetadata,
) error {
return nil
}
repoDB.UpdateSignaturesValidityFn = func(repo string, signedManifestDigest godigest.Digest,
) error {
return ErrTestError
}
err = repodb.ParseRepo("repo", repoDB, storeController, log)
So(err, ShouldNotBeNil)
})
Convey("GetSignatureLayersInfo errors", func() {
// get notation signature layers info
badNotationManifestContent := ispec.Manifest{
Subject: &ispec.Descriptor{
Digest: "123",
},
ArtifactType: "application/vnd.cncf.notary.signature",
}
badNotationManifestBlob, err := json.Marshal(badNotationManifestContent)
So(err, ShouldBeNil)
imageStore.GetImageManifestFn = func(repo, reference string) ([]byte, godigest.Digest, string, error) {
return badNotationManifestBlob, "", "", nil
}
// wrong number of layers of notation manifest
err = repodb.ParseRepo("repo", repoDB, storeController, log)
So(err, ShouldNotBeNil)
notationManifestContent := ispec.Manifest{
Subject: &ispec.Descriptor{
Digest: "123",
},
ArtifactType: "application/vnd.cncf.notary.signature",
Layers: []ispec.Descriptor{{MediaType: ispec.MediaTypeImageLayer}},
}
notationManifestBlob, err := json.Marshal(notationManifestContent)
So(err, ShouldBeNil)
imageStore.GetImageManifestFn = func(repo, reference string) ([]byte, godigest.Digest, string, error) {
return notationManifestBlob, "", "", nil
}
imageStore.GetBlobContentFn = func(repo string, digest godigest.Digest) ([]byte, error) {
return []byte{}, ErrTestError
}
// unable to get layer content
err = repodb.ParseRepo("repo", repoDB, storeController, log)
So(err, ShouldNotBeNil)
_, _, cosignManifestContent, _ := test.GetRandomImageComponents(10)
_, _, signedManifest, _ := test.GetRandomImageComponents(10)
signatureTag, err := test.GetCosignSignatureTagForManifest(signedManifest)
So(err, ShouldBeNil)
cosignManifestContent.Annotations = map[string]string{ispec.AnnotationRefName: signatureTag}
cosignManifestBlob, err := json.Marshal(cosignManifestContent)
So(err, ShouldBeNil)
imageStore.GetImageManifestFn = func(repo, reference string) ([]byte, godigest.Digest, string, error) {
return cosignManifestBlob, "", "", nil
}
indexContent := ispec.Index{
Manifests: []ispec.Descriptor{
{
Digest: godigest.FromString("cosignSig"),
MediaType: ispec.MediaTypeImageManifest,
Annotations: map[string]string{
ispec.AnnotationRefName: signatureTag,
},
},
},
}
indexBlob, err := json.Marshal(indexContent)
So(err, ShouldBeNil)
imageStore.GetIndexContentFn = func(repo string) ([]byte, error) {
return indexBlob, nil
}
// unable to get layer content
err = repodb.ParseRepo("repo", repoDB, storeController, log)
So(err, ShouldNotBeNil)
})
})
})
@@ -534,3 +630,22 @@ func skipIt(t *testing.T) {
t.Skip("Skipping testing without AWS S3 mock server")
}
}
func TestGetSignatureLayersInfo(t *testing.T) {
Convey("wrong signature type", t, func() {
layers, err := repodb.GetSignatureLayersInfo("repo", "tag", "123", "wrong signature type", []byte{},
nil, log.NewLogger("debug", ""))
So(err, ShouldBeNil)
So(layers, ShouldBeEmpty)
})
Convey("error while unmarshaling manifest content", t, func() {
_, err := repodb.GetSignatureLayersInfo("repo", "tag", "123", signatures.CosignSignature, []byte("bad manifest"),
nil, log.NewLogger("debug", ""))
So(err, ShouldNotBeNil)
_, err = repodb.GetSignatureLayersInfo("repo", "tag", "123", signatures.NotationSignature, []byte("bad manifest"),
nil, log.NewLogger("debug", ""))
So(err, ShouldNotBeNil)
})
}