storage: add VerifyArtifact method
Signed-off-by: Hidde Beydals <hidde@hhh.computer>
This commit is contained in:
parent
62fd433e79
commit
67e9c94abf
|
|
@ -21,6 +21,7 @@ import (
|
|||
"compress/gzip"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"io"
|
||||
"io/fs"
|
||||
"net/url"
|
||||
|
|
@ -325,6 +326,35 @@ func (s *Storage) ArtifactExist(artifact v1.Artifact) bool {
|
|||
return fi.Mode().IsRegular()
|
||||
}
|
||||
|
||||
// VerifyArtifact verifies if the Digest of the v1.Artifact matches the digest
|
||||
// of the file in Storage. It returns an error if the digests don't match, or
|
||||
// if it can't be verified.
|
||||
func (s *Storage) VerifyArtifact(artifact v1.Artifact) error {
|
||||
if artifact.Digest == "" {
|
||||
return fmt.Errorf("artifact has no digest")
|
||||
}
|
||||
|
||||
d, err := digest.Parse(artifact.Digest)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse artifact digest '%s': %w", artifact.Digest, err)
|
||||
}
|
||||
|
||||
f, err := os.Open(s.LocalPath(artifact))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
verifier := d.Verifier()
|
||||
if _, err = io.Copy(verifier, f); err != nil {
|
||||
return err
|
||||
}
|
||||
if !verifier.Verified() {
|
||||
return fmt.Errorf("computed digest doesn't match '%s'", d.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ArchiveFileFilter must return true if a file should not be included in the archive after inspecting the given path
|
||||
// and/or os.FileInfo.
|
||||
type ArchiveFileFilter func(p string, fi os.FileInfo) bool
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
|
@ -718,3 +719,61 @@ func TestStorage_GarbageCollect(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStorage_VerifyArtifact(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
dir := t.TempDir()
|
||||
s, err := NewStorage(dir, "", 0, 0)
|
||||
g.Expect(err).ToNot(HaveOccurred(), "failed to create new storage")
|
||||
|
||||
g.Expect(os.WriteFile(filepath.Join(dir, "artifact"), []byte("test"), 0o600)).To(Succeed())
|
||||
|
||||
t.Run("artifact without digest", func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
err := s.VerifyArtifact(sourcev1.Artifact{})
|
||||
g.Expect(err).To(HaveOccurred())
|
||||
g.Expect(err).To(MatchError("artifact has no digest"))
|
||||
})
|
||||
|
||||
t.Run("artifact with invalid digest", func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
err := s.VerifyArtifact(sourcev1.Artifact{Digest: "invalid"})
|
||||
g.Expect(err).To(HaveOccurred())
|
||||
g.Expect(err).To(MatchError("failed to parse artifact digest 'invalid': invalid checksum digest format"))
|
||||
})
|
||||
|
||||
t.Run("artifact with invalid path", func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
err := s.VerifyArtifact(sourcev1.Artifact{
|
||||
Digest: "sha256:9ba7a35ce8acd3557fe30680ef193ca7a36bb5dc62788f30de7122a0a5beab69",
|
||||
Path: "invalid",
|
||||
})
|
||||
g.Expect(err).To(HaveOccurred())
|
||||
g.Expect(errors.Is(err, os.ErrNotExist)).To(BeTrue())
|
||||
})
|
||||
|
||||
t.Run("artifact with digest mismatch", func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
err := s.VerifyArtifact(sourcev1.Artifact{
|
||||
Digest: "sha256:9ba7a35ce8acd3557fe30680ef193ca7a36bb5dc62788f30de7122a0a5beab69",
|
||||
Path: "artifact",
|
||||
})
|
||||
g.Expect(err).To(HaveOccurred())
|
||||
g.Expect(err).To(MatchError("computed digest doesn't match 'sha256:9ba7a35ce8acd3557fe30680ef193ca7a36bb5dc62788f30de7122a0a5beab69'"))
|
||||
})
|
||||
|
||||
t.Run("artifact with digest match", func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
err := s.VerifyArtifact(sourcev1.Artifact{
|
||||
Digest: "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
|
||||
Path: "artifact",
|
||||
})
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue