feat: add support for oci1.1 cosign signatures(using referrers) (#1963)

- Cosign supports 2 types of signature formats:

	1. Using tag -> each new signature of the same manifest is
	added as a new layer of the signature manifest having that
	specific tag("{alghoritm}-{digest_of_signed_manifest}.sig")

	2. Using referrers -> each new signature of the same manifest is
	added as a new manifest

- For adding these cosign signature to metadb, we reserved index 0 of the
list of cosign signatures for tag-based signatures. When a new tag-based
signature is added for the same manifest, the element on first position
in its list of cosign signatures(in metadb) will be updated/overwritten.
When a new cosign signature(using referrers) will be added for the same
manifest this new signature will be appended to the list of cosign
signatures.

Signed-off-by: Andreea-Lupu <andreealupu1470@yahoo.com>
This commit is contained in:
Andreea Lupu
2023-11-07 00:09:39 +02:00
committed by GitHub
parent 6a66a9b9b4
commit d5065513f5
21 changed files with 511 additions and 85 deletions
+34 -14
View File
@@ -813,7 +813,7 @@ func (bdw *BoltDB) GetMultipleRepoMeta(ctx context.Context, filter func(repoMeta
}
func (bdw *BoltDB) AddManifestSignature(repo string, signedManifestDigest godigest.Digest,
sygMeta mTypes.SignatureMetadata,
sigMeta mTypes.SignatureMetadata,
) error {
err := bdw.DB.Update(func(tx *bbolt.Tx) error {
repoMetaBuck := tx.Bucket([]byte(RepoMetaBuck))
@@ -829,11 +829,11 @@ func (bdw *BoltDB) AddManifestSignature(repo string, signedManifestDigest godige
Signatures: map[string]*proto_go.ManifestSignatures{
signedManifestDigest.String(): {
Map: map[string]*proto_go.SignaturesInfo{
sygMeta.SignatureType: {
sigMeta.SignatureType: {
List: []*proto_go.SignatureInfo{
{
SignatureManifestDigest: sygMeta.SignatureDigest,
LayersInfo: mConvert.GetProtoLayersInfo(sygMeta.LayersInfo),
SignatureManifestDigest: sigMeta.SignatureDigest,
LayersInfo: mConvert.GetProtoLayersInfo(sigMeta.LayersInfo),
},
},
},
@@ -867,26 +867,46 @@ func (bdw *BoltDB) AddManifestSignature(repo string, signedManifestDigest godige
}
signatureSlice := &proto_go.SignaturesInfo{List: []*proto_go.SignatureInfo{}}
if sigSlice, found := manifestSignatures.Map[sygMeta.SignatureType]; found {
if sigSlice, found := manifestSignatures.Map[sigMeta.SignatureType]; found {
signatureSlice = sigSlice
}
if !common.ProtoSignatureAlreadyExists(signatureSlice.List, sygMeta) {
switch sygMeta.SignatureType {
if !common.ProtoSignatureAlreadyExists(signatureSlice.List, sigMeta) {
switch sigMeta.SignatureType {
case zcommon.NotationSignature:
signatureSlice.List = append(signatureSlice.List, &proto_go.SignatureInfo{
SignatureManifestDigest: sygMeta.SignatureDigest,
LayersInfo: mConvert.GetProtoLayersInfo(sygMeta.LayersInfo),
SignatureManifestDigest: sigMeta.SignatureDigest,
LayersInfo: mConvert.GetProtoLayersInfo(sigMeta.LayersInfo),
})
case zcommon.CosignSignature:
signatureSlice.List = []*proto_go.SignatureInfo{{
SignatureManifestDigest: sygMeta.SignatureDigest,
LayersInfo: mConvert.GetProtoLayersInfo(sygMeta.LayersInfo),
}}
newCosignSig := &proto_go.SignatureInfo{
SignatureManifestDigest: sigMeta.SignatureDigest,
LayersInfo: mConvert.GetProtoLayersInfo(sigMeta.LayersInfo),
}
if zcommon.IsCosignTag(sigMeta.SignatureTag) {
// the entry for "sha256-{digest}.sig" signatures should be overwritten if
// it exists or added on the first position if it doesn't exist
if len(signatureSlice.GetList()) == 0 {
signatureSlice.List = []*proto_go.SignatureInfo{newCosignSig}
} else {
signatureSlice.List[0] = newCosignSig
}
} else {
// the first position should be reserved for "sha256-{digest}.sig" signatures
if len(signatureSlice.GetList()) == 0 {
signatureSlice.List = []*proto_go.SignatureInfo{{
SignatureManifestDigest: "",
LayersInfo: []*proto_go.LayersInfo{},
}}
}
signatureSlice.List = append(signatureSlice.List, newCosignSig)
}
}
}
manifestSignatures.Map[sygMeta.SignatureType] = signatureSlice
manifestSignatures.Map[sigMeta.SignatureType] = signatureSlice
protoRepoMeta.Signatures[signedManifestDigest.String()] = manifestSignatures
return setProtoRepoMeta(protoRepoMeta, repoMetaBuck)
+34 -14
View File
@@ -1041,7 +1041,7 @@ func (dwr *DynamoDB) UpdateSignaturesValidity(repo string, manifestDigest godige
}
func (dwr *DynamoDB) AddManifestSignature(repo string, signedManifestDigest godigest.Digest,
sygMeta mTypes.SignatureMetadata,
sigMeta mTypes.SignatureMetadata,
) error {
protoRepoMeta, err := dwr.getProtoRepoMeta(context.Background(), repo)
if err != nil {
@@ -1054,11 +1054,11 @@ func (dwr *DynamoDB) AddManifestSignature(repo string, signedManifestDigest godi
Signatures: map[string]*proto_go.ManifestSignatures{
signedManifestDigest.String(): {
Map: map[string]*proto_go.SignaturesInfo{
sygMeta.SignatureType: {
sigMeta.SignatureType: {
List: []*proto_go.SignatureInfo{
{
SignatureManifestDigest: sygMeta.SignatureDigest,
LayersInfo: mConvert.GetProtoLayersInfo(sygMeta.LayersInfo),
SignatureManifestDigest: sigMeta.SignatureDigest,
LayersInfo: mConvert.GetProtoLayersInfo(sigMeta.LayersInfo),
},
},
},
@@ -1083,26 +1083,46 @@ func (dwr *DynamoDB) AddManifestSignature(repo string, signedManifestDigest godi
}
signatureSlice := &proto_go.SignaturesInfo{List: []*proto_go.SignatureInfo{}}
if sigSlice, found := manifestSignatures.Map[sygMeta.SignatureType]; found {
if sigSlice, found := manifestSignatures.Map[sigMeta.SignatureType]; found {
signatureSlice = sigSlice
}
if !common.ProtoSignatureAlreadyExists(signatureSlice.List, sygMeta) {
switch sygMeta.SignatureType {
if !common.ProtoSignatureAlreadyExists(signatureSlice.List, sigMeta) {
switch sigMeta.SignatureType {
case zcommon.NotationSignature:
signatureSlice.List = append(signatureSlice.List, &proto_go.SignatureInfo{
SignatureManifestDigest: sygMeta.SignatureDigest,
LayersInfo: mConvert.GetProtoLayersInfo(sygMeta.LayersInfo),
SignatureManifestDigest: sigMeta.SignatureDigest,
LayersInfo: mConvert.GetProtoLayersInfo(sigMeta.LayersInfo),
})
case zcommon.CosignSignature:
signatureSlice.List = []*proto_go.SignatureInfo{{
SignatureManifestDigest: sygMeta.SignatureDigest,
LayersInfo: mConvert.GetProtoLayersInfo(sygMeta.LayersInfo),
}}
newCosignSig := &proto_go.SignatureInfo{
SignatureManifestDigest: sigMeta.SignatureDigest,
LayersInfo: mConvert.GetProtoLayersInfo(sigMeta.LayersInfo),
}
if zcommon.IsCosignTag(sigMeta.SignatureTag) {
// the entry for "sha256-{digest}.sig" signatures should be overwritten if
// it exists or added on the first position if it doesn't exist
if len(signatureSlice.GetList()) == 0 {
signatureSlice.List = []*proto_go.SignatureInfo{newCosignSig}
} else {
signatureSlice.List[0] = newCosignSig
}
} else {
// the first position should be reserved for "sha256-{digest}.sig" signatures
if len(signatureSlice.GetList()) == 0 {
signatureSlice.List = []*proto_go.SignatureInfo{{
SignatureManifestDigest: "",
LayersInfo: []*proto_go.LayersInfo{},
}}
}
signatureSlice.List = append(signatureSlice.List, newCosignSig)
}
}
}
manifestSignatures.Map[sygMeta.SignatureType] = signatureSlice
manifestSignatures.Map[sigMeta.SignatureType] = signatureSlice
protoRepoMeta.Signatures[signedManifestDigest.String()] = manifestSignatures
return dwr.setProtoRepoMeta(protoRepoMeta.Name, protoRepoMeta)
+17 -1
View File
@@ -1290,18 +1290,31 @@ func RunMetaDBTests(t *testing.T, metaDB mTypes.MetaDB, preparationFuncs ...func
})
So(err, ShouldBeNil)
err = metaDB.AddManifestSignature(repo1, image1.Digest, mTypes.SignatureMetadata{
SignatureType: "cosign",
SignatureTag: fmt.Sprintf("sha256-%s.sig", image1.Digest.Encoded()),
SignatureDigest: "digesttag",
LayersInfo: []mTypes.LayerInfo{{LayerDigest: "layer-digest", LayerContent: []byte{10}}},
})
So(err, ShouldBeNil)
repoMeta, err := metaDB.GetRepoMeta(ctx, repo1)
So(err, ShouldBeNil)
So(repoMeta.Signatures[image1.Digest.String()]["cosign"][0].SignatureManifestDigest,
ShouldResemble, "digesttag")
So(repoMeta.Signatures[image1.Digest.String()]["cosign"][1].SignatureManifestDigest,
ShouldResemble, "digest")
imageMeta, err := metaDB.GetImageMeta(image1.Digest)
fullImageMeta := convert.GetFullImageMeta(tag1, repoMeta, imageMeta)
So(err, ShouldBeNil)
So(fullImageMeta.Signatures["cosign"][0].SignatureManifestDigest, ShouldResemble, "digest")
So(fullImageMeta.Signatures["cosign"][0].SignatureManifestDigest, ShouldResemble, "digesttag")
So(fullImageMeta.Signatures["cosign"][0].LayersInfo[0].LayerDigest, ShouldResemble, "layer-digest")
So(fullImageMeta.Signatures["cosign"][0].LayersInfo[0].LayerContent[0], ShouldEqual, 10)
So(fullImageMeta.Signatures["cosign"][1].SignatureManifestDigest, ShouldResemble, "digest")
So(fullImageMeta.Signatures["cosign"][1].LayersInfo[0].LayerDigest, ShouldResemble, "layer-digest")
So(fullImageMeta.Signatures["cosign"][1].LayersInfo[0].LayerContent[0], ShouldEqual, 10)
})
Convey("Test UpdateSignaturesValidity", func() {
@@ -1320,6 +1333,7 @@ func RunMetaDBTests(t *testing.T, metaDB mTypes.MetaDB, preparationFuncs ...func
err = metaDB.AddManifestSignature(repo1, image1.Digest(), mTypes.SignatureMetadata{
SignatureType: "cosign",
SignatureDigest: image1.DigestStr(),
SignatureTag: fmt.Sprintf("sha256-%s.sig", image1.Digest().Encoded()),
LayersInfo: []mTypes.LayerInfo{layerInfo},
})
So(err, ShouldBeNil)
@@ -1442,6 +1456,7 @@ func RunMetaDBTests(t *testing.T, metaDB mTypes.MetaDB, preparationFuncs ...func
err := metaDB.AddManifestSignature(repo1, image1.Digest(), mTypes.SignatureMetadata{
SignatureType: "cosign",
SignatureTag: fmt.Sprintf("sha256-%s.sig", image1.Digest().Encoded()),
SignatureDigest: "digest",
})
So(err, ShouldBeNil)
@@ -1467,6 +1482,7 @@ func RunMetaDBTests(t *testing.T, metaDB mTypes.MetaDB, preparationFuncs ...func
err = metaDB.AddManifestSignature(repo1, image1.Digest(), mTypes.SignatureMetadata{
SignatureType: "cosign",
SignatureTag: fmt.Sprintf("sha256-%s.sig", image1.Digest().Encoded()),
SignatureDigest: "digest",
})
So(err, ShouldBeNil)
+6
View File
@@ -289,6 +289,7 @@ func SetImageMetaFromInput(ctx context.Context, repo, reference, mediaType strin
mTypes.SignatureMetadata{
SignatureType: sigType,
SignatureDigest: digest.String(),
SignatureTag: reference,
LayersInfo: layers,
})
if err != nil {
@@ -342,6 +343,11 @@ func isSignature(reference string, manifestContent ispec.Manifest) (bool, string
return true, NotationType, manifestContent.Subject.Digest
}
// check cosign signature
if manifestArtifactType == zcommon.ArtifactTypeCosign && manifestContent.Subject != nil {
return true, CosignType, manifestContent.Subject.Digest
}
if tag := reference; zcommon.IsCosignTag(reference) {
prefixLen := len("sha256-")
digestLen := 64
+1
View File
@@ -298,6 +298,7 @@ type SignatureInfo struct {
type SignatureMetadata struct {
SignatureType string
SignatureDigest string
SignatureTag string
LayersInfo []LayerInfo
}