fix: call notation-go libs instead of using notation binary (#1104)

fix: add loading notation path

Signed-off-by: Andreea-Lupu <andreealupu1470@yahoo.com>
Co-authored-by: Roxana Nemulescu <roxana.nemulescu@gmail.com>
This commit is contained in:
Andreea Lupu
2023-02-13 20:43:52 +02:00
committed by GitHub
parent 2377d62344
commit ee95ab0ffc
21 changed files with 1731 additions and 333 deletions
+74 -79
View File
@@ -18,7 +18,6 @@ import (
"net/http/httptest"
"net/url"
"os"
"os/exec"
"path"
"regexp"
"strconv"
@@ -3964,53 +3963,28 @@ func TestImageSignatures(t *testing.T) {
tdir := t.TempDir()
_ = os.Chdir(tdir)
// "notation" (notaryv2) doesn't yet support exported apis, so use the binary instead
notPath, err := exec.LookPath("notation")
So(notPath, ShouldNotBeNil)
test.NotationPathLock.Lock()
defer test.NotationPathLock.Unlock()
test.LoadNotationPath(tdir)
err = test.GenerateNotationCerts(tdir, "good")
So(err, ShouldBeNil)
os.Setenv("XDG_CONFIG_HOME", tdir)
// generate a keypair
cmd := exec.Command("notation", "cert", "generate-test", "--trust", "good")
err = cmd.Run()
err = test.GenerateNotationCerts(tdir, "bad")
So(err, ShouldBeNil)
// generate another keypair
cmd = exec.Command("notation", "cert", "generate-test", "--trust", "bad")
err = cmd.Run()
So(err, ShouldBeNil)
// sign the image
image := fmt.Sprintf("localhost:%s/%s:%s", port, repoName, "1.0")
cmd = exec.Command("notation", "sign", "--key", "good", "--plain-http", image)
err = cmd.Run()
err = test.SignWithNotation("good", image, tdir)
So(err, ShouldBeNil)
// verify the image
cmd = exec.Command("notation", "verify", "--cert", "good", "--plain-http", image)
out, err := cmd.CombinedOutput()
err = test.VerifyWithNotation(image, tdir)
So(err, ShouldBeNil)
msg := string(out)
So(msg, ShouldNotBeEmpty)
So(strings.Contains(msg, "verification failure"), ShouldBeFalse)
// check list
cmd = exec.Command("notation", "list", "--plain-http", image)
out, err = cmd.CombinedOutput()
sigs, err := test.ListNotarySignatures(image, tdir)
So(len(sigs), ShouldEqual, 1)
So(err, ShouldBeNil)
msg = strings.TrimSuffix(string(out), "\n")
So(msg, ShouldNotBeEmpty)
_, err = godigest.Parse(msg)
So(err, ShouldBeNil)
// verify the image with incorrect key
cmd = exec.Command("notation", "verify", "--cert", "bad", "--plain-http", image)
out, err = cmd.CombinedOutput()
So(err, ShouldNotBeNil)
msg = string(out)
So(msg, ShouldNotBeEmpty)
So(strings.Contains(msg, "verification failure"), ShouldBeTrue)
// check unsupported manifest media type
resp, err := resty.R().SetHeader("Content-Type", "application/vnd.unsupported.image.manifest.v1+json").
@@ -4027,49 +4001,45 @@ func TestImageSignatures(t *testing.T) {
Convey("Validate corrupted signature", func() {
// verify with corrupted signature
resp, err = resty.R().SetQueryParam("artifactType", notreg.ArtifactTypeNotation).Get(
fmt.Sprintf("%s/oras/artifacts/v1/%s/manifests/%s/referrers", baseURL, repoName, digest.String()))
fmt.Sprintf("%s/v2/%s/referrers/%s", baseURL, repoName, digest.String()))
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
var refs api.ReferenceList
var refs ispec.Index
err = json.Unmarshal(resp.Body(), &refs)
So(err, ShouldBeNil)
So(len(refs.References), ShouldEqual, 1)
So(len(refs.Manifests), ShouldEqual, 1)
err = os.WriteFile(path.Join(dir, repoName, "blobs",
strings.ReplaceAll(refs.References[0].Digest.String(), ":", "/")), []byte("corrupt"), 0o600)
strings.ReplaceAll(refs.Manifests[0].Digest.String(), ":", "/")), []byte("corrupt"), 0o600)
So(err, ShouldBeNil)
resp, err = resty.R().SetQueryParam("artifactType", notreg.ArtifactTypeNotation).Get(
fmt.Sprintf("%s/oras/artifacts/v1/%s/manifests/%s/referrers", baseURL, repoName, digest.String()))
fmt.Sprintf("%s/v2/%s/referrers/%s", baseURL, repoName, digest.String()))
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusNotFound)
cmd = exec.Command("notation", "verify", "--cert", "good", "--plain-http", image)
out, err = cmd.CombinedOutput()
So(resp.StatusCode(), ShouldEqual, http.StatusInternalServerError)
err = test.VerifyWithNotation(image, tdir)
So(err, ShouldNotBeNil)
msg = string(out)
So(msg, ShouldNotBeEmpty)
})
Convey("Validate deleted signature", func() {
// verify with corrupted signature
resp, err = resty.R().SetQueryParam("artifactType", notreg.ArtifactTypeNotation).Get(
fmt.Sprintf("%s/oras/artifacts/v1/%s/manifests/%s/referrers", baseURL, repoName, digest.String()))
fmt.Sprintf("%s/v2/%s/referrers/%s", baseURL, repoName, digest.String()))
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
var refs api.ReferenceList
var refs ispec.Index
err = json.Unmarshal(resp.Body(), &refs)
So(err, ShouldBeNil)
So(len(refs.References), ShouldEqual, 1)
So(len(refs.Manifests), ShouldEqual, 1)
err = os.Remove(path.Join(dir, repoName, "blobs",
strings.ReplaceAll(refs.References[0].Digest.String(), ":", "/")))
strings.ReplaceAll(refs.Manifests[0].Digest.String(), ":", "/")))
So(err, ShouldBeNil)
resp, err = resty.R().SetQueryParam("artifactType", notreg.ArtifactTypeNotation).Get(
fmt.Sprintf("%s/oras/artifacts/v1/%s/manifests/%s/referrers", baseURL, repoName, digest.String()))
fmt.Sprintf("%s/v2/%s/referrers/%s", baseURL, repoName, digest.String()))
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusNotFound)
cmd = exec.Command("notation", "verify", "--cert", "good", "--plain-http", image)
out, err = cmd.CombinedOutput()
err = test.VerifyWithNotation(image, tdir)
So(err, ShouldNotBeNil)
msg = string(out)
So(msg, ShouldNotBeEmpty)
})
})
@@ -5192,7 +5162,7 @@ func TestManifestImageIndex(t *testing.T) {
Layers: layers,
Manifest: manifest,
}, baseURL, repoName)
So(err, ShouldBeNil)
So(err, ShouldNotBeNil)
content, err = json.Marshal(manifest)
So(err, ShouldBeNil)
@@ -5217,7 +5187,7 @@ func TestManifestImageIndex(t *testing.T) {
Layers: layers,
Manifest: manifest,
}, baseURL, repoName)
So(err, ShouldBeNil)
So(err, ShouldNotBeNil)
content, err = json.Marshal(manifest)
So(err, ShouldBeNil)
@@ -5273,7 +5243,7 @@ func TestManifestImageIndex(t *testing.T) {
Layers: layers,
Manifest: manifest,
}, baseURL, repoName)
So(err, ShouldBeNil)
So(err, ShouldNotBeNil)
content, err = json.Marshal(manifest)
So(err, ShouldBeNil)
digest = godigest.FromBytes(content)
@@ -5446,7 +5416,7 @@ func TestManifestImageIndex(t *testing.T) {
Layers: layers,
Manifest: manifest,
}, baseURL, repoName)
So(err, ShouldBeNil)
So(err, ShouldNotBeNil)
content, err = json.Marshal(manifest)
So(err, ShouldBeNil)
digest = godigest.FromBytes(content)
@@ -6200,23 +6170,17 @@ func TestGCSignaturesAndUntaggedManifests(t *testing.T) {
So(err, ShouldBeNil)
// "notation" (notaryv2) doesn't yet support exported apis, so use the binary instead
notPath, err := exec.LookPath("notation")
So(notPath, ShouldNotBeNil)
So(err, ShouldBeNil)
test.NotationPathLock.Lock()
defer test.NotationPathLock.Unlock()
os.Setenv("XDG_CONFIG_HOME", tdir)
test.LoadNotationPath(tdir)
// generate a keypair
cmd := exec.Command("notation", "cert", "generate-test", "--trust", "good")
output, err := cmd.CombinedOutput()
t.Log(string(output))
err = test.GenerateNotationCerts(tdir, "good")
So(err, ShouldBeNil)
// sign the image
cmd = exec.Command("notation", "sign", "--key", "good", "--plain-http", image)
output, err = cmd.CombinedOutput()
t.Log(string(output))
err = test.SignWithNotation("good", image, tdir)
So(err, ShouldBeNil)
// get cosign signature manifest
@@ -6228,15 +6192,21 @@ func TestGCSignaturesAndUntaggedManifests(t *testing.T) {
// get notation signature manifest
resp, err = resty.R().SetQueryParam("artifactType", notreg.ArtifactTypeNotation).Get(
fmt.Sprintf("%s/oras/artifacts/v1/%s/manifests/%s/referrers", baseURL, repoName, digest.String()))
fmt.Sprintf("%s/v2/%s/referrers/%s", baseURL, repoName, digest.String()))
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
var index ispec.Index
err = json.Unmarshal(resp.Body(), &index)
So(err, ShouldBeNil)
So(len(index.Manifests), ShouldEqual, 1)
Convey("Trigger gcNotationSignatures() error", func() {
var refs api.ReferenceList
var refs ispec.Index
err = json.Unmarshal(resp.Body(), &refs)
err := os.Chmod(path.Join(dir, repoName, "blobs", "sha256", refs.References[0].Digest.Encoded()), 0o000)
err := os.Chmod(path.Join(dir, repoName, "blobs", "sha256", refs.Manifests[0].Digest.Encoded()), 0o000)
So(err, ShouldBeNil)
// trigger gc
@@ -6250,9 +6220,26 @@ func TestGCSignaturesAndUntaggedManifests(t *testing.T) {
Manifest: manifest,
Tag: tag,
}, baseURL, repoName)
So(err, ShouldNotBeNil)
err = os.Chmod(path.Join(dir, repoName, "blobs", "sha256", refs.Manifests[0].Digest.Encoded()), 0o755)
So(err, ShouldBeNil)
err = os.Chmod(path.Join(dir, repoName, "blobs", "sha256", refs.References[0].Digest.Encoded()), 0o755)
content, err := os.ReadFile(path.Join(dir, repoName, "blobs", "sha256", refs.Manifests[0].Digest.Encoded()))
So(err, ShouldBeNil)
err = os.WriteFile(path.Join(dir, repoName, "blobs", "sha256", refs.Manifests[0].Digest.Encoded()), []byte("corrupt"), 0o600) //nolint:lll
So(err, ShouldBeNil)
err = test.UploadImage(
test.Image{
Config: cfg,
Layers: layers,
Manifest: manifest,
Tag: tag,
}, baseURL, repoName)
So(err, ShouldNotBeNil)
err = os.WriteFile(path.Join(dir, repoName, "blobs", "sha256", refs.Manifests[0].Digest.Encoded()), content, 0o600)
So(err, ShouldBeNil)
})
@@ -6296,14 +6283,22 @@ func TestGCSignaturesAndUntaggedManifests(t *testing.T) {
So(resp.StatusCode(), ShouldEqual, http.StatusNotFound)
resp, err = resty.R().SetQueryParam("artifactType", notreg.ArtifactTypeNotation).Get(
fmt.Sprintf("%s/oras/artifacts/v1/%s/manifests/%s/referrers", baseURL, repoName, digest.String()))
fmt.Sprintf("%s/v2/%s/referrers/%s", baseURL, repoName, digest.String()))
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusNotFound)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
err = json.Unmarshal(resp.Body(), &index)
So(err, ShouldBeNil)
So(len(index.Manifests), ShouldEqual, 0)
resp, err = resty.R().SetQueryParam("artifactType", notreg.ArtifactTypeNotation).Get(
fmt.Sprintf("%s/oras/artifacts/v1/%s/manifests/%s/referrers", baseURL, repoName, newManifestDigest.String()))
fmt.Sprintf("%s/v2/%s/referrers/%s", baseURL, repoName, newManifestDigest.String()))
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusNotFound)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
err = json.Unmarshal(resp.Body(), &index)
So(err, ShouldBeNil)
So(len(index.Manifests), ShouldEqual, 0)
// untagged image should also be gc'ed
resp, err = resty.R().Get(baseURL + fmt.Sprintf("/v2/%s/manifests/%s", repoName, untaggedManifestDigest))
+12 -7
View File
@@ -431,7 +431,7 @@ func getReferrers(ctx context.Context, routeHandler *RouteHandler,
artifactTypes []string,
) (ispec.Index, error) {
references, err := imgStore.GetReferrers(name, digest, artifactTypes)
if err != nil {
if err != nil || len(references.Manifests) == 0 {
if routeHandler.c.Config.Extensions != nil &&
routeHandler.c.Config.Extensions.Sync != nil &&
*routeHandler.c.Config.Extensions.Sync.Enable {
@@ -495,11 +495,11 @@ func (rh *RouteHandler) GetReferrers(response http.ResponseWriter, request *http
if errors.Is(err, zerr.ErrManifestNotFound) || errors.Is(err, zerr.ErrRepoNotFound) {
rh.c.Log.Error().Err(err).Str("name", name).Str("digest", digest.String()).Msg("manifest not found")
response.WriteHeader(http.StatusNotFound)
} else {
rh.c.Log.Error().Err(err).Str("name", name).Str("digest", digest.String()).Msg("unable to get references")
response.WriteHeader(http.StatusInternalServerError)
}
rh.c.Log.Error().Err(err).Str("name", name).Str("digest", digest.String()).Msg("unable to get references")
response.WriteHeader(http.StatusInternalServerError)
return
}
@@ -1662,7 +1662,7 @@ func getOrasReferrers(ctx context.Context, routeHandler *RouteHandler,
if routeHandler.c.Config.Extensions != nil &&
routeHandler.c.Config.Extensions.Sync != nil &&
*routeHandler.c.Config.Extensions.Sync.Enable {
routeHandler.c.Log.Info().Msgf("signature not found, trying to get signature %s:%s by syncing on demand",
routeHandler.c.Log.Info().Msgf("artifact not found, trying to get artifact %s:%s by syncing on demand",
name, digest.String())
errSync := ext.SyncOneImage(ctx, routeHandler.c.Config, routeHandler.c.StoreController,
@@ -1736,8 +1736,13 @@ func (rh *RouteHandler) GetOrasReferrers(response http.ResponseWriter, request *
refs, err := getOrasReferrers(request.Context(), rh, imgStore, name, digest, artifactType) //nolint:contextcheck
if err != nil {
rh.c.Log.Error().Err(err).Str("name", name).Str("digest", digest.String()).Msg("unable to get references")
response.WriteHeader(http.StatusNotFound)
if errors.Is(err, zerr.ErrManifestNotFound) || errors.Is(err, zerr.ErrRepoNotFound) {
rh.c.Log.Error().Err(err).Str("name", name).Str("digest", digest.String()).Msg("manifest not found")
response.WriteHeader(http.StatusNotFound)
} else {
rh.c.Log.Error().Err(err).Str("name", name).Str("digest", digest.String()).Msg("unable to get references")
response.WriteHeader(http.StatusInternalServerError)
}
return
}