// // Copyright 2021 The Sigstore Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package layout import ( "fmt" "runtime" "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/v2/pkg/oci" "github.com/sigstore/cosign/v2/pkg/oci/mutate" "github.com/sigstore/cosign/v2/pkg/oci/signed" "github.com/sigstore/cosign/v2/pkg/oci/static" ) func TestReadWrite(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("test is flaky on windows, see https://github.com/sigstore/cosign/v2/issues/1389") } // write random signed image to disk 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 we have 5 attestations attImg, err := imageIndex.Attestations() if err != nil { t.Fatal(err) } atts, err := attImg.Get() if err != nil { t.Fatal(err) } if len(atts) != 5 { t.Fatal("expected 5 attestations") } // make sure signatures are correct sigImage, err := imageIndex.Signatures() if err != nil { t.Fatal(err) } sigs, err := sigImage.Get() if err != nil { t.Fatal(err) } want := 6 if len(sigs) != want { t.Fatal("didn't get the expected number of signatures") } // make sure the annotation is correct for i, sig := range sigs { annotations, err := sig.Annotations() if err != nil { t.Fatal(err) } val, ok := annotations["layer"] if !ok { t.Fatal("expected annotation doesn't exist on signature") } if val != fmt.Sprintf("%d", i) { t.Fatal("expected annotation isn't correct") } } } 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) } } want = 5 // Add 5 attestations for i := 0; i < want; i++ { sig, err := static.NewAttestation([]byte(fmt.Sprintf("%d", i))) if err != nil { t.Fatalf("static.NewSignature() = %v", err) } si, err = mutate.AttachAttestationToImage(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) } }