mirror of
https://github.com/project-zot/zot.git
synced 2026-06-16 12:28:01 +08:00
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:
@@ -262,7 +262,21 @@ func (olu BaseOciLayoutUtils) checkCosignSignature(name string, digest godigest.
|
||||
reference := fmt.Sprintf("sha256-%s.sig", digest.Encoded())
|
||||
|
||||
_, _, _, err := imageStore.GetImageManifest(name, reference) //nolint: dogsled
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
mediaType := common.ArtifactTypeCosign
|
||||
|
||||
referrers, err := imageStore.GetReferrers(name, digest, []string{mediaType})
|
||||
if err != nil {
|
||||
olu.Log.Info().Err(err).Str("repository", name).Str("digest",
|
||||
digest.String()).Str("mediatype", mediaType).Msg("invalid cosign signature")
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
if len(referrers.Manifests) == 0 {
|
||||
olu.Log.Info().Err(err).Str("repository", name).Str("digest",
|
||||
digest.String()).Msg("invalid cosign signature")
|
||||
|
||||
|
||||
@@ -331,6 +331,100 @@ func TestBaseOciLayoutUtils(t *testing.T) {
|
||||
isSigned = olu.CheckManifestSignature(repo, manifestList[0].Digest)
|
||||
So(isSigned, ShouldBeTrue)
|
||||
})
|
||||
|
||||
//nolint: dupl
|
||||
Convey("CheckManifestSignature: cosign(tag)", t, func() {
|
||||
// checkCosignSignature -> true (tag)
|
||||
dir := t.TempDir()
|
||||
|
||||
port := tcommon.GetFreePort()
|
||||
baseURL := tcommon.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
conf.Storage.RootDirectory = dir
|
||||
defaultVal := true
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
||||
}
|
||||
|
||||
conf.Extensions.Search.CVE = nil
|
||||
|
||||
ctlr := api.NewController(conf)
|
||||
|
||||
ctlrManager := tcommon.NewControllerManager(ctlr)
|
||||
ctlrManager.StartAndWait(port)
|
||||
defer ctlrManager.StopServer()
|
||||
|
||||
// push test image to repo
|
||||
image := CreateRandomImage()
|
||||
|
||||
repo := "repo2"
|
||||
tag := "1.0.2"
|
||||
err := UploadImage(image, baseURL, repo, tag)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
olu := ociutils.NewBaseOciLayoutUtils(ctlr.StoreController, log.NewLogger("debug", ""))
|
||||
manifestList, err := olu.GetImageManifests(repo)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(manifestList), ShouldEqual, 1)
|
||||
|
||||
isSigned := olu.CheckManifestSignature(repo, manifestList[0].Digest)
|
||||
So(isSigned, ShouldBeFalse)
|
||||
|
||||
// checkCosignSignature -> true (tag)
|
||||
err = signature.SignImageUsingCosign(fmt.Sprintf("%s:%s", repo, tag), port, false)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
isSigned = olu.CheckManifestSignature(repo, manifestList[0].Digest)
|
||||
So(isSigned, ShouldBeTrue)
|
||||
})
|
||||
|
||||
//nolint: dupl
|
||||
Convey("CheckManifestSignature: cosign(with referrers)", t, func() {
|
||||
// checkCosignSignature -> true (referrers)
|
||||
dir := t.TempDir()
|
||||
|
||||
port := tcommon.GetFreePort()
|
||||
baseURL := tcommon.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
conf.Storage.RootDirectory = dir
|
||||
defaultVal := true
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
||||
}
|
||||
|
||||
conf.Extensions.Search.CVE = nil
|
||||
|
||||
ctlr := api.NewController(conf)
|
||||
|
||||
ctlrManager := tcommon.NewControllerManager(ctlr)
|
||||
ctlrManager.StartAndWait(port)
|
||||
defer ctlrManager.StopServer()
|
||||
|
||||
// push test image to repo
|
||||
image := CreateRandomImage()
|
||||
|
||||
repo := "repo3"
|
||||
tag := "1.0.3"
|
||||
err := UploadImage(image, baseURL, repo, tag)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
olu := ociutils.NewBaseOciLayoutUtils(ctlr.StoreController, log.NewLogger("debug", ""))
|
||||
manifestList, err := olu.GetImageManifests(repo)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(manifestList), ShouldEqual, 1)
|
||||
|
||||
isSigned := olu.CheckManifestSignature(repo, manifestList[0].Digest)
|
||||
So(isSigned, ShouldBeFalse)
|
||||
|
||||
// checkCosignSignature -> true (referrers)
|
||||
err = signature.SignImageUsingCosign(fmt.Sprintf("%s:%s", repo, tag), port, true)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
isSigned = olu.CheckManifestSignature(repo, manifestList[0].Digest)
|
||||
So(isSigned, ShouldBeTrue)
|
||||
})
|
||||
}
|
||||
|
||||
func TestExtractImageDetails(t *testing.T) {
|
||||
|
||||
@@ -30,7 +30,7 @@ func GetCosignSignatureTagForDigest(manifestDigest godigest.Digest) string {
|
||||
return manifestDigest.Algorithm().String() + "-" + manifestDigest.Encoded() + ".sig"
|
||||
}
|
||||
|
||||
func SignImageUsingCosign(repoTag, port string) error {
|
||||
func SignImageUsingCosign(repoTag, port string, withReferrers bool) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -59,13 +59,21 @@ func SignImageUsingCosign(repoTag, port string) error {
|
||||
|
||||
const timeoutPeriod = 5
|
||||
|
||||
signOpts := options.SignOptions{
|
||||
Registry: options.RegistryOptions{AllowInsecure: true},
|
||||
AnnotationOptions: options.AnnotationOptions{Annotations: []string{"tag=1.0"}},
|
||||
Upload: true,
|
||||
}
|
||||
|
||||
if withReferrers {
|
||||
signOpts.RegistryExperimental = options.RegistryExperimentalOptions{
|
||||
RegistryReferrersMode: options.RegistryReferrersModeOCI11,
|
||||
}
|
||||
}
|
||||
|
||||
// sign the image
|
||||
return sign.SignCmd(&options.RootOptions{Verbose: true, Timeout: timeoutPeriod * time.Minute},
|
||||
options.KeyOpts{KeyRef: path.Join(tdir, "cosign.key"), PassFunc: generate.GetPass},
|
||||
options.SignOptions{
|
||||
Registry: options.RegistryOptions{AllowInsecure: true},
|
||||
AnnotationOptions: options.AnnotationOptions{Annotations: []string{"tag=1.0"}},
|
||||
Upload: true,
|
||||
},
|
||||
signOpts,
|
||||
[]string{imageURL})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user