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

Add layout package for writing and loading signatures from disk #1040

Merged
merged 8 commits into from
Nov 19, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Code review comments, also support for passing in an empty hash to Si…
…gnedImage

Signed-off-by: Priya Wadhwa <priyawadhwa@google.com>
  • Loading branch information
Priya Wadhwa committed Nov 17, 2021
commit add535a0d22e5c32eb1c381257537d2e00eaa2fd
18 changes: 11 additions & 7 deletions pkg/oci/layout/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package layout

import (
"errors"
"fmt"

v1 "github.com/google/go-containerregistry/pkg/v1"
Expand Down Expand Up @@ -74,8 +75,15 @@ func (i *index) Attachment(name string) (oci.File, error) {
}

// SignedImage implements oci.SignedImageIndex
// if an empty hash is passed in, return the original image that was signed
func (i *index) SignedImage(h v1.Hash) (oci.SignedImage, error) {
img, err := i.Image(h)
var img v1.Image
var err error
if h.String() == ":" {
img, err = i.imageByAnnotation(imageAnnotation)
} else {
img, err = i.Image(h)
}
if err != nil {
return nil, err
}
Expand All @@ -91,14 +99,10 @@ func (i *index) imageByAnnotation(annotation string) (v1.Image, error) {
}
for _, m := range manifest.Manifests {
if _, ok := m.Annotations[annotation]; ok {
img, err := i.Image(m.Digest)
if err != nil {
return nil, err
}
return img, nil
return i.Image(m.Digest)
}
}
return nil, fmt.Errorf("unable to find image")
return nil, errors.New("unable to find image")
}

// SignedImageIndex implements oci.SignedImageIndex
Expand Down
69 changes: 50 additions & 19 deletions pkg/oci/layout/write_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,36 @@ import (
"fmt"
"testing"

"github.com/google/go-cmp/cmp"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/random"
"github.com/sigstore/cosign/pkg/oci"
"github.com/sigstore/cosign/pkg/oci/mutate"
"github.com/sigstore/cosign/pkg/oci/signed"
"github.com/sigstore/cosign/pkg/oci/static"
)

func TestReadWrite(t *testing.T) {
// write random signed image to disk
i, err := random.Image(300 /* byteSize */, 7 /* layers */)
if err != nil {
t.Fatalf("random.Image() = %v", err)
}
si := signed.Image(i)

want := 6 // Add 6 signatures
for i := 0; i < want; i++ {
annotationOption := static.WithAnnotations(map[string]string{"layer": fmt.Sprintf("%d", i)})
sig, err := static.NewSignature(nil, fmt.Sprintf("%d", i), annotationOption)
if err != nil {
t.Fatalf("static.NewSignature() = %v", err)
}
si, err = mutate.AttachSignatureToImage(si, sig)
if err != nil {
t.Fatalf("SignEntity() = %v", err)
}
}

si := randomSignedImage(t)
tmp := t.TempDir()
if err := WriteSignedImage(tmp, si); err != nil {
t.Fatal(err)
}

// read the image and make sure the signatures exist
imageIndex, err := SignedImageIndex(tmp)
if err != nil {
t.Fatal(err)
}
gotSignedImage, err := imageIndex.SignedImage(v1.Hash{})
if err != nil {
t.Fatal(err)
}
// compare the image we read with the one we wrote
compareDigests(t, si, gotSignedImage)

// make sure signatures are correct
sigImage, err := imageIndex.Signatures()
if err != nil {
t.Fatal(err)
Expand All @@ -63,6 +57,7 @@ func TestReadWrite(t *testing.T) {
if err != nil {
t.Fatal(err)
}
want := 6
if len(sigs) != want {
t.Fatal("didn't get the expected number of signatures")
}
Expand All @@ -81,3 +76,39 @@ func TestReadWrite(t *testing.T) {
}
}
}

func randomSignedImage(t *testing.T) oci.SignedImage {
i, err := random.Image(300 /* byteSize */, 7 /* layers */)
if err != nil {
t.Fatalf("random.Image() = %v", err)
}
si := signed.Image(i)

want := 6 // Add 6 signatures
for i := 0; i < want; i++ {
annotationOption := static.WithAnnotations(map[string]string{"layer": fmt.Sprintf("%d", i)})
sig, err := static.NewSignature(nil, fmt.Sprintf("%d", i), annotationOption)
if err != nil {
t.Fatalf("static.NewSignature() = %v", err)
}
si, err = mutate.AttachSignatureToImage(si, sig)
if err != nil {
t.Fatalf("SignEntity() = %v", err)
}
}
return si
}

func compareDigests(t *testing.T, img1 oci.SignedImage, img2 oci.SignedImage) {
d1, err := img1.Digest()
if err != nil {
t.Fatal(err)
}
d2, err := img2.Digest()
if err != nil {
t.Fatal(err)
}
if d := cmp.Diff(d1, d2); d != "" {
t.Fatalf("digests are different: %s", d)
}
}