Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for oci1.1 cosign signatures #1963

Merged
merged 1 commit into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion pkg/cli/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,27 @@ func isCosignSigned(ctx context.Context, repo, digestStr string, searchConf Sear
_, err := makeGETRequest(ctx, URL, username, password, searchConf.VerifyTLS,
searchConf.Debug, &result, searchConf.ResultWriter)

return err == nil
if err == nil {
return true
}

var referrers ispec.Index

artifactType := url.QueryEscape(common.ArtifactTypeCosign)
URL = fmt.Sprintf("%s/v2/%s/referrers/%s?artifactType=%s",
adodon2go marked this conversation as resolved.
Show resolved Hide resolved
searchConf.ServURL, repo, digestStr, artifactType)

_, err = makeGETRequest(ctx, URL, username, password, searchConf.VerifyTLS,
searchConf.Debug, &referrers, searchConf.ResultWriter)
if err != nil {
return false
}

if len(referrers.Manifests) == 0 {
return false
}

return true
}

func (p *requestsPool) submitJob(job *httpJob) {
Expand Down
66 changes: 59 additions & 7 deletions pkg/cli/client/image_cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,17 @@ import (
"zotregistry.io/zot/pkg/test/signature"
)

//nolint:dupl
func TestSignature(t *testing.T) {
space := regexp.MustCompile(`\s+`)
repoName := "repo7"

Convey("Test from real server", t, func() {
Convey("Test with cosign signature(tag)", t, func() {
currentWorkingDir, err := os.Getwd()
So(err, ShouldBeNil)

defer func() { _ = os.Chdir(currentWorkingDir) }()

currentDir := t.TempDir()
err = os.Chdir(currentDir)
So(err, ShouldBeNil)
Expand All @@ -59,7 +63,6 @@ func TestSignature(t *testing.T) {
cm.StartAndWait(conf.HTTP.Port)
defer cm.StopServer()

repoName := "repo7"
image := CreateDefaultImage()
err = UploadImage(image, url, repoName, "1.0")
So(err, ShouldBeNil)
Expand Down Expand Up @@ -108,15 +111,68 @@ func TestSignature(t *testing.T) {
actual = strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
So(actual, ShouldContainSubstring, "repo7 1.0 linux/amd64 db573b01 true 854B")
})

Convey("Test with cosign signature(withReferrers)", t, func() {
currentWorkingDir, err := os.Getwd()
So(err, ShouldBeNil)

defer func() { _ = os.Chdir(currentWorkingDir) }()

currentDir := t.TempDir()
err = os.Chdir(currentDir)
So(err, ShouldBeNil)

port := test.GetFreePort()
url := test.GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
defaultVal := true
conf.Extensions = &extconf.ExtensionConfig{
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
}
ctlr := api.NewController(conf)
ctlr.Config.Storage.RootDirectory = currentDir
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(conf.HTTP.Port)
defer cm.StopServer()

err = os.Chdir(currentWorkingDir)
err = UploadImage(CreateDefaultImage(), url, repoName, "0.0.1")
So(err, ShouldBeNil)

err = signature.SignImageUsingCosign("repo7:0.0.1", port, true)
adodon2go marked this conversation as resolved.
Show resolved Hide resolved
So(err, ShouldBeNil)

searchConfig := getTestSearchConfig(url, client.NewSearchService())

t.Logf("%s", ctlr.Config.Storage.RootDirectory)

buff := &bytes.Buffer{}
searchConfig.ResultWriter = buff
err = client.SearchAllImagesGQL(searchConfig)
So(err, ShouldBeNil)

actual := strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
So(actual, ShouldContainSubstring, "repo7 0.0.1 linux/amd64 db573b01 true 854B")

t.Log("Test getting all images using rest calls to get catalog and individual manifests")
buff = &bytes.Buffer{}
searchConfig.ResultWriter = buff
err = client.SearchAllImages(searchConfig)
So(err, ShouldBeNil)

actual = strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
So(actual, ShouldContainSubstring, "repo7 0.0.1 linux/amd64 db573b01 true 854B")
})

Convey("Test with notation signature", t, func() {
currentWorkingDir, err := os.Getwd()
So(err, ShouldBeNil)

defer func() { _ = os.Chdir(currentWorkingDir) }()

currentDir := t.TempDir()
err = os.Chdir(currentDir)
So(err, ShouldBeNil)
Expand All @@ -135,7 +191,6 @@ func TestSignature(t *testing.T) {
cm.StartAndWait(conf.HTTP.Port)
defer cm.StopServer()

repoName := "repo7"
err = UploadImage(CreateDefaultImage(), url, repoName, "0.0.1")
So(err, ShouldBeNil)

Expand Down Expand Up @@ -164,9 +219,6 @@ func TestSignature(t *testing.T) {
actual = strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
So(actual, ShouldContainSubstring, "repo7 0.0.1 linux/amd64 db573b01 true 854B")

err = os.Chdir(currentWorkingDir)
So(err, ShouldBeNil)
})
}

Expand Down
1 change: 1 addition & 0 deletions pkg/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const (
// same value as github.com/notaryproject/notation-go/registry.ArtifactTypeNotation (assert by internal test).
// reason used: to reduce zot minimal binary size (otherwise adds oras.land/oras-go/v2 deps).
ArtifactTypeNotation = "application/vnd.cncf.notary.signature"
ArtifactTypeCosign = "application/vnd.dev.cosign.artifact.sig.v1+json"
)

var cosignTagRule = regexp.MustCompile(`sha256\-.+\.sig`)
Expand Down
16 changes: 8 additions & 8 deletions pkg/extensions/search/search_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1349,7 +1349,7 @@ func TestExpandedRepoInfo(t *testing.T) {
}
So(found, ShouldEqual, true)

err = signature.SignImageUsingCosign("zot-cve-test:0.0.1", port)
err = signature.SignImageUsingCosign("zot-cve-test:0.0.1", port, false)
adodon2go marked this conversation as resolved.
Show resolved Hide resolved
So(err, ShouldBeNil)

resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query))
Expand Down Expand Up @@ -1421,7 +1421,7 @@ func TestExpandedRepoInfo(t *testing.T) {
}
So(found, ShouldEqual, true)

err = signature.SignImageUsingCosign("zot-test@"+testManifestDigest.String(), port)
err = signature.SignImageUsingCosign("zot-test@"+testManifestDigest.String(), port, false)
So(err, ShouldBeNil)

resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "/query?query=" + url.QueryEscape(query))
Expand Down Expand Up @@ -3759,7 +3759,7 @@ func TestGlobalSearchFiltering(t *testing.T) {
)
So(err, ShouldBeNil)

err = signature.SignImageUsingCosign("signed-repo:test", port)
err = signature.SignImageUsingCosign("signed-repo:test", port, false)
So(err, ShouldBeNil)

query := `{
Expand Down Expand Up @@ -4323,7 +4323,7 @@ func TestMetaDBWhenSigningImages(t *testing.T) {
`

Convey("Sign with cosign", func() {
err = signature.SignImageUsingCosign("repo1:1.0.1", port)
err = signature.SignImageUsingCosign("repo1:1.0.1", port, false)
So(err, ShouldBeNil)

resp, err := resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(queryImage1))
Expand Down Expand Up @@ -4403,7 +4403,7 @@ func TestMetaDBWhenSigningImages(t *testing.T) {
},
}

err := signature.SignImageUsingCosign("repo1:1.0.1", port)
err := signature.SignImageUsingCosign("repo1:1.0.1", port, false)
So(err, ShouldNotBeNil)
})
})
Expand Down Expand Up @@ -4443,7 +4443,7 @@ func TestMetaDBWhenSigningImages(t *testing.T) {
})

Convey("Sign with cosign index", func() {
err = signature.SignImageUsingCosign("repo1:index", port)
err = signature.SignImageUsingCosign("repo1:index", port, false)
So(err, ShouldBeNil)

resp, err := resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(queryIndex))
Expand Down Expand Up @@ -4572,7 +4572,7 @@ func RunMetaDBIndexTests(baseURL, port string) {
responseImage := responseImages[0]
So(len(responseImage.Manifests), ShouldEqual, 3)

err = signature.SignImageUsingCosign(fmt.Sprintf("repo@%s", multiarchImage.DigestStr()), port)
err = signature.SignImageUsingCosign(fmt.Sprintf("repo@%s", multiarchImage.DigestStr()), port, false)
So(err, ShouldBeNil)

resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query))
Expand Down Expand Up @@ -5301,7 +5301,7 @@ func TestMetaDBWhenDeletingImages(t *testing.T) {

Convey("Delete a cosign signature", func() {
repo := "repo1"
err := signature.SignImageUsingCosign("repo1:1.0.1", port)
err := signature.SignImageUsingCosign("repo1:1.0.1", port, false)
So(err, ShouldBeNil)

query := `
Expand Down
2 changes: 1 addition & 1 deletion pkg/extensions/sync/references/oci.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func (ref OciReferences) IsSigned(ctx context.Context, remoteRepo, subjectDigest
return false
}

if len(getNotationManifestsFromOCIRefs(index)) > 0 {
if len(getNotationManifestsFromOCIRefs(index)) > 0 || len(getCosignManifestsFromOCIRefs(index)) > 0 {
return true
}

Expand Down
21 changes: 7 additions & 14 deletions pkg/extensions/sync/references/references.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"zotregistry.io/zot/pkg/common"
client "zotregistry.io/zot/pkg/extensions/sync/httpclient"
"zotregistry.io/zot/pkg/log"
"zotregistry.io/zot/pkg/meta"
mTypes "zotregistry.io/zot/pkg/meta/types"
"zotregistry.io/zot/pkg/storage"
storageTypes "zotregistry.io/zot/pkg/storage/types"
Expand Down Expand Up @@ -218,20 +217,14 @@ func getNotationManifestsFromOCIRefs(ociRefs ispec.Index) []ispec.Descriptor {
return notaryManifests
}

func addSigToMeta(
metaDB mTypes.MetaDB, repo, sigType, tag string, signedManifestDig, referenceDigest godigest.Digest,
referenceBuf []byte, imageStore storageTypes.ImageStore, log log.Logger,
) error {
layersInfo, errGetLayers := meta.GetSignatureLayersInfo(repo, tag, referenceDigest.String(),
sigType, referenceBuf, imageStore, log)
func getCosignManifestsFromOCIRefs(ociRefs ispec.Index) []ispec.Descriptor {
cosignManifests := []ispec.Descriptor{}

if errGetLayers != nil {
return errGetLayers
for _, ref := range ociRefs.Manifests {
if ref.ArtifactType == common.ArtifactTypeCosign {
cosignManifests = append(cosignManifests, ref)
}
}

return metaDB.AddManifestSignature(repo, signedManifestDig, mTypes.SignatureMetadata{
SignatureType: sigType,
SignatureDigest: referenceDigest.String(),
LayersInfo: layersInfo,
})
return cosignManifests
}
11 changes: 0 additions & 11 deletions pkg/extensions/sync/references/references_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,14 +440,3 @@ func TestCompareArtifactRefs(t *testing.T) {
}
})
}

func TestAddSigToMeta(t *testing.T) {
Convey("Test addSigToMeta", t, func() {
imageStore := mocks.MockedImageStore{}
metaDB := mocks.MetaDBMock{}

err := addSigToMeta(metaDB, "repo", "cosign", "tag", godigest.FromString("signedmanifest"),
godigest.FromString("reference"), []byte("bad"), imageStore, log.Logger{})
So(err, ShouldNotBeNil)
})
}
Loading
Loading