...

Source file src/github.com/sigstore/cosign/v2/pkg/oci/mutate/mutate_test.go

Documentation: github.com/sigstore/cosign/v2/pkg/oci/mutate

     1  //
     2  // Copyright 2021 The Sigstore Authors.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  package mutate
    17  
    18  import (
    19  	"crypto/rand"
    20  	"errors"
    21  	"fmt"
    22  	"reflect"
    23  	"testing"
    24  
    25  	v1 "github.com/google/go-containerregistry/pkg/v1"
    26  	"github.com/google/go-containerregistry/pkg/v1/mutate"
    27  	"github.com/google/go-containerregistry/pkg/v1/random"
    28  	"github.com/sigstore/cosign/v2/pkg/oci"
    29  	"github.com/sigstore/cosign/v2/pkg/oci/signed"
    30  	"github.com/sigstore/cosign/v2/pkg/oci/static"
    31  )
    32  
    33  func TestAppendManifests(t *testing.T) {
    34  	ii, err := random.Index(300 /* bytes */, 3 /* layers */, 5 /* images */)
    35  	if err != nil {
    36  		t.Fatalf("random.Index() = %v", err)
    37  	}
    38  	i2, err := random.Image(300 /* bytes */, 3 /* layers */)
    39  	if err != nil {
    40  		t.Fatalf("random.Image() = %v", err)
    41  	}
    42  	ii3, err := random.Index(300 /* bytes */, 3 /* layers */, 5 /* images */)
    43  	if err != nil {
    44  		t.Fatalf("random.Index() = %v", err)
    45  	}
    46  	ii = mutate.AppendManifests(ii, mutate.IndexAddendum{
    47  		Add: i2,
    48  	}, mutate.IndexAddendum{
    49  		Add: ii3,
    50  	})
    51  	ii2, err := random.Index(300 /* bytes */, 3 /* layers */, 5 /* images */)
    52  	if err != nil {
    53  		t.Fatalf("random.Index() = %v", err)
    54  	}
    55  	i1, err := random.Image(300 /* bytes */, 3 /* layers */)
    56  	if err != nil {
    57  		t.Fatalf("random.Image() = %v", err)
    58  	}
    59  
    60  	tests := []struct {
    61  		name string
    62  		fn   func(v1.ImageIndex) v1.ImageIndex
    63  	}{{
    64  		name: "unsigned",
    65  		fn: func(in v1.ImageIndex) v1.ImageIndex {
    66  			return in
    67  		},
    68  	}, {
    69  		name: "signed",
    70  		fn: func(in v1.ImageIndex) v1.ImageIndex {
    71  			return signed.ImageIndex(in)
    72  		},
    73  	}}
    74  
    75  	for _, test := range tests {
    76  		t.Run(test.name, func(t *testing.T) {
    77  			ni := AppendManifests(test.fn(ii), IndexAddendum{
    78  				Add: signed.Image(i1),
    79  			}, IndexAddendum{
    80  				Add: signed.ImageIndex(ii2),
    81  			})
    82  			if err != nil {
    83  				t.Fatalf("AppendManifests() = %v", err)
    84  			}
    85  
    86  			im, err := ni.IndexManifest()
    87  			if err != nil {
    88  				t.Fatalf("IndexManifest() = %v", err)
    89  			}
    90  
    91  			if got, want := len(im.Manifests), 7+2; got != want {
    92  				t.Errorf("len(im.Manifests) = %d, wanted %d", got, want)
    93  			}
    94  
    95  			if sigs, err := ni.Signatures(); err != nil {
    96  				t.Errorf("Signatures() = %v", err)
    97  			} else if sl, err := sigs.Get(); err != nil {
    98  				t.Errorf("Get() = %v", err)
    99  			} else if len(sl) != 0 {
   100  				t.Errorf("len(Get()) = %d, wanted 0", len(sl))
   101  			}
   102  
   103  			if atts, err := ni.Attestations(); err != nil {
   104  				t.Errorf("Attestations() = %v", err)
   105  			} else if al, err := atts.Get(); err != nil {
   106  				t.Errorf("Get() = %v", err)
   107  			} else if len(al) != 0 {
   108  				t.Errorf("len(Get()) = %d, wanted 0", len(al))
   109  			}
   110  
   111  			d1, err := i1.Digest()
   112  			if err != nil {
   113  				t.Fatalf("Digest() = %v", err)
   114  			}
   115  			if _, err := ni.SignedImage(d1); err != nil {
   116  				t.Fatalf("SignedImage() = %v", err)
   117  			}
   118  
   119  			d2, err := ii2.Digest()
   120  			if err != nil {
   121  				t.Fatalf("Digest() = %v", err)
   122  			}
   123  			if _, err := ni.SignedImageIndex(d2); err != nil {
   124  				t.Fatalf("SignedImageIndex() = %v", err)
   125  			}
   126  
   127  			if se, err := ni.SignedImage(d2); err == nil {
   128  				t.Fatalf("SignedImage() = %#v, wanted error", se)
   129  			}
   130  			if se, err := ni.SignedImageIndex(d1); err == nil {
   131  				t.Fatalf("SignedImageIndex() = %#v, wanted error", se)
   132  			}
   133  
   134  			d3, err := i2.Digest()
   135  			if err != nil {
   136  				t.Fatalf("Digest() = %v", err)
   137  			}
   138  			if _, err := ni.SignedImage(d3); err != nil {
   139  				t.Fatalf("SignedImage() = %v", err)
   140  			}
   141  
   142  			d4, err := ii3.Digest()
   143  			if err != nil {
   144  				t.Fatalf("Digest() = %v", err)
   145  			}
   146  			if _, err := ni.SignedImageIndex(d4); err != nil {
   147  				t.Fatalf("SignedImageIndex() = %v", err)
   148  			}
   149  		})
   150  	}
   151  }
   152  
   153  func TestSignEntity(t *testing.T) {
   154  	i, err := random.Image(300 /* bytes */, 3 /* layers */)
   155  	if err != nil {
   156  		t.Fatalf("random.Image() = %v", err)
   157  	}
   158  	si := signed.Image(i)
   159  
   160  	ii, err := random.Index(300 /* bytes */, 3 /* layers */, 5 /* images */)
   161  	if err != nil {
   162  		t.Fatalf("random.Index() = %v", err)
   163  	}
   164  	sii := signed.ImageIndex(ii)
   165  
   166  	// Create an explicitly unknown implementation of oci.SignedEntity, which we
   167  	// feed through the table tests below.
   168  	want := make([]byte, 300)
   169  	rand.Read(want)
   170  	orig, err := static.NewFile(want)
   171  	if err != nil {
   172  		t.Fatalf("static.NewFile() = %v", err)
   173  	}
   174  	sunk, err := AttachFileToUnknown(sii, "sbom", orig)
   175  	if err != nil {
   176  		t.Fatalf("AttachFileToUnknown() = %v", err)
   177  	}
   178  
   179  	t.Run("attach SBOMs", func(t *testing.T) {
   180  		for _, se := range []oci.SignedEntity{si, sii, sunk} {
   181  			want := make([]byte, 300)
   182  			rand.Read(want)
   183  
   184  			orig, err := static.NewFile(want)
   185  			if err != nil {
   186  				t.Fatalf("static.NewFile() = %v", err)
   187  			}
   188  			se, err = AttachFileToEntity(se, "sbom", orig)
   189  			if err != nil {
   190  				t.Fatalf("AttachFileToEntity() = %v", err)
   191  			}
   192  
   193  			f, err := se.Attachment("sbom")
   194  			if err != nil {
   195  				t.Fatalf("Attachment(sbom) = %v", err)
   196  			}
   197  			got, err := f.Payload()
   198  			if err != nil {
   199  				t.Fatalf("Payload() = %v", err)
   200  			}
   201  			if !reflect.DeepEqual(want, got) {
   202  				t.Errorf("Payload() = %v, wanted %v", got, want)
   203  			}
   204  
   205  			f, err = se.Attachment("gitbom")
   206  			if err == nil {
   207  				t.Errorf("Attachment(gitbom) = %T, wanted error", f)
   208  			}
   209  		}
   210  	})
   211  
   212  	t.Run("without duplicate detector (signature)", func(t *testing.T) {
   213  		for _, se := range []oci.SignedEntity{si, sii, sunk} {
   214  			orig, err := static.NewSignature(nil, "")
   215  			if err != nil {
   216  				t.Fatalf("static.NewSignature() = %v", err)
   217  			}
   218  			se, err = AttachSignatureToEntity(se, orig)
   219  			if err != nil {
   220  				t.Fatalf("AttachSignatureToEntity() = %v", err)
   221  			}
   222  
   223  			for i := 2; i < 10; i++ {
   224  				sig, err := static.NewSignature(nil, fmt.Sprintf("%d", i))
   225  				if err != nil {
   226  					t.Fatalf("static.NewSignature() = %v", err)
   227  				}
   228  
   229  				se, err = AttachSignatureToEntity(se, sig)
   230  				if err != nil {
   231  					t.Fatalf("AttachSignatureToEntity() = %v", err)
   232  				}
   233  
   234  				sigs, err := se.Signatures()
   235  				if err != nil {
   236  					t.Fatalf("Signatures() = %v", err)
   237  				}
   238  				if sl, err := sigs.Get(); err != nil {
   239  					t.Fatalf("Get() = %v", err)
   240  				} else if len(sl) != i {
   241  					t.Errorf("len(Get()) = %d, wanted %d", len(sl), i)
   242  				}
   243  			}
   244  		}
   245  	})
   246  
   247  	t.Run("without duplicate detector (attestation)", func(t *testing.T) {
   248  		for _, se := range []oci.SignedEntity{si, sii, sunk} {
   249  			orig, err := static.NewAttestation([]byte("payload"))
   250  			if err != nil {
   251  				t.Fatalf("static.NewAttestation() = %v", err)
   252  			}
   253  			se, err = AttachAttestationToEntity(se, orig)
   254  			if err != nil {
   255  				t.Fatalf("AttachAttestationToEntity() = %v", err)
   256  			}
   257  
   258  			for i := 2; i < 10; i++ {
   259  				sig, err := static.NewAttestation([]byte(fmt.Sprintf("%d", i)))
   260  				if err != nil {
   261  					t.Fatalf("static.NewAttestation() = %v", err)
   262  				}
   263  
   264  				se, err = AttachAttestationToEntity(se, sig)
   265  				if err != nil {
   266  					t.Fatalf("AttachAttestationToEntity() = %v", err)
   267  				}
   268  
   269  				atts, err := se.Attestations()
   270  				if err != nil {
   271  					t.Fatalf("Attestations() = %v", err)
   272  				}
   273  				if al, err := atts.Get(); err != nil {
   274  					t.Fatalf("Get() = %v", err)
   275  				} else if len(al) != i {
   276  					t.Errorf("len(Get()) = %d, wanted %d", len(al), i)
   277  				}
   278  			}
   279  		}
   280  	})
   281  
   282  	t.Run("with duplicate detector (signature)", func(t *testing.T) {
   283  		for _, se := range []oci.SignedEntity{si, sii, sunk} {
   284  			orig, err := static.NewSignature(nil, "")
   285  			if err != nil {
   286  				t.Fatalf("static.NewSignature() = %v", err)
   287  			}
   288  			se, err = AttachSignatureToEntity(se, orig)
   289  			if err != nil {
   290  				t.Fatalf("AttachSignatureToEntity() = %v", err)
   291  			}
   292  
   293  			dd := &dupe{
   294  				sig: orig,
   295  			}
   296  
   297  			for i := 2; i < 10; i++ {
   298  				sig, err := static.NewSignature(nil, fmt.Sprintf("%d", i))
   299  				if err != nil {
   300  					t.Fatalf("static.NewSignature() = %v", err)
   301  				}
   302  
   303  				se, err = AttachSignatureToEntity(se, sig, WithDupeDetector(dd))
   304  				if err != nil {
   305  					t.Fatalf("AttachSignatureToEntity() = %v", err)
   306  				}
   307  
   308  				sigs, err := se.Signatures()
   309  				if err != nil {
   310  					t.Fatalf("Signatures() = %v", err)
   311  				}
   312  				if sl, err := sigs.Get(); err != nil {
   313  					t.Fatalf("Get() = %v", err)
   314  				} else if len(sl) != 1 {
   315  					t.Errorf("len(Get()) = %d, wanted %d", len(sl), i)
   316  				}
   317  			}
   318  		}
   319  	})
   320  
   321  	t.Run("with duplicate detector (attestation)", func(t *testing.T) {
   322  		for _, se := range []oci.SignedEntity{si, sii, sunk} {
   323  			orig, err := static.NewAttestation([]byte("blah"))
   324  			if err != nil {
   325  				t.Fatalf("static.NewAttestation() = %v", err)
   326  			}
   327  			se, err = AttachAttestationToEntity(se, orig)
   328  			if err != nil {
   329  				t.Fatalf("AttachAttestationToEntity() = %v", err)
   330  			}
   331  
   332  			dd := &dupe{
   333  				sig: orig,
   334  			}
   335  
   336  			for i := 2; i < 10; i++ {
   337  				sig, err := static.NewAttestation([]byte(fmt.Sprintf("%d", i)))
   338  				if err != nil {
   339  					t.Fatalf("static.NewAttestation() = %v", err)
   340  				}
   341  
   342  				se, err = AttachAttestationToEntity(se, sig, WithDupeDetector(dd))
   343  				if err != nil {
   344  					t.Fatalf("AttachAttestationToEntity() = %v", err)
   345  				}
   346  
   347  				atts, err := se.Attestations()
   348  				if err != nil {
   349  					t.Fatalf("Attestations() = %v", err)
   350  				}
   351  				if al, err := atts.Get(); err != nil {
   352  					t.Fatalf("Get() = %v", err)
   353  				} else if len(al) != 1 {
   354  					t.Errorf("len(Get()) = %d, wanted %d", len(al), 1)
   355  				}
   356  			}
   357  		}
   358  	})
   359  
   360  	t.Run("with erroring duplicate detector (signature)", func(t *testing.T) {
   361  		for _, se := range []oci.SignedEntity{si, sii, sunk} {
   362  			orig, err := static.NewSignature(nil, "")
   363  			if err != nil {
   364  				t.Fatalf("static.NewSignature() = %v", err)
   365  			}
   366  			se, err = AttachSignatureToEntity(se, orig)
   367  			if err != nil {
   368  				t.Fatalf("AttachSignatureToEntity() = %v", err)
   369  			}
   370  
   371  			want := errors.New("expected error")
   372  			dd := &dupe{
   373  				err: want,
   374  			}
   375  
   376  			for i := 2; i < 10; i++ {
   377  				sig, err := static.NewSignature(nil, fmt.Sprintf("%d", i))
   378  				if err != nil {
   379  					t.Fatalf("static.NewSignature() = %v", err)
   380  				}
   381  
   382  				se, err = AttachSignatureToEntity(se, sig, WithDupeDetector(dd))
   383  				if err != nil {
   384  					t.Fatalf("AttachSignatureToEntity() = %v", err)
   385  				}
   386  
   387  				if _, got := se.Signatures(); !errors.Is(got, want) {
   388  					t.Fatalf("Signatures() = %v, wanted %v", got, want)
   389  				}
   390  			}
   391  		}
   392  	})
   393  
   394  	t.Run("with erroring duplicate detector (attestation)", func(t *testing.T) {
   395  		for _, se := range []oci.SignedEntity{si, sii, sunk} {
   396  			orig, err := static.NewAttestation([]byte("blah"))
   397  			if err != nil {
   398  				t.Fatalf("static.NewAttestation() = %v", err)
   399  			}
   400  			se, err = AttachAttestationToEntity(se, orig)
   401  			if err != nil {
   402  				t.Fatalf("AttachAttestationToEntity() = %v", err)
   403  			}
   404  
   405  			want := errors.New("expected error")
   406  			dd := &dupe{
   407  				err: want,
   408  			}
   409  
   410  			for i := 2; i < 10; i++ {
   411  				sig, err := static.NewAttestation([]byte(fmt.Sprintf("%d", i)))
   412  				if err != nil {
   413  					t.Fatalf("static.NewAttestation() = %v", err)
   414  				}
   415  
   416  				se, err = AttachAttestationToEntity(se, sig, WithDupeDetector(dd))
   417  				if err != nil {
   418  					t.Fatalf("AttachAttestationToEntity() = %v", err)
   419  				}
   420  
   421  				if _, got := se.Attestations(); !errors.Is(got, want) {
   422  					t.Fatalf("Attestations() = %v, wanted %v", got, want)
   423  				}
   424  			}
   425  		}
   426  	})
   427  
   428  	t.Run("with replace op (attestation)", func(t *testing.T) {
   429  		for _, se := range []oci.SignedEntity{si, sii, sunk} {
   430  			orig, err := static.NewAttestation([]byte("blah"))
   431  			if err != nil {
   432  				t.Fatalf("static.NewAttestation() = %v", err)
   433  			}
   434  			se, err = AttachAttestationToEntity(se, orig)
   435  			if err != nil {
   436  				t.Fatalf("AttachAttestationToEntity() = %v", err)
   437  			}
   438  
   439  			ro := &replaceAll{}
   440  
   441  			for i := 2; i < 10; i++ {
   442  				sig, err := static.NewAttestation([]byte(fmt.Sprintf("%d", i)))
   443  				if err != nil {
   444  					t.Fatalf("static.NewAttestation() = %v", err)
   445  				}
   446  
   447  				se, err = AttachAttestationToEntity(se, sig, WithReplaceOp(ro))
   448  				if err != nil {
   449  					t.Fatalf("AttachAttestationToEntity() = %v", err)
   450  				}
   451  
   452  				atts, err := se.Attestations()
   453  				if err != nil {
   454  					t.Fatalf("Attestations() = %v", err)
   455  				}
   456  				if al, err := atts.Get(); err != nil {
   457  					t.Fatalf("Get() = %v", err)
   458  				} else if len(al) != 1 {
   459  					t.Errorf("len(Get()) = %d, wanted %d", len(al), 1)
   460  				}
   461  			}
   462  		}
   463  	})
   464  }
   465  
   466  type dupe struct {
   467  	sig oci.Signature
   468  	err error
   469  }
   470  
   471  var _ DupeDetector = (*dupe)(nil)
   472  
   473  // Find implements DupeDetector
   474  func (d *dupe) Find(oci.Signatures, oci.Signature) (oci.Signature, error) {
   475  	return d.sig, d.err
   476  }
   477  
   478  type replaceAll struct {
   479  }
   480  
   481  func (r *replaceAll) Replace(signatures oci.Signatures, o oci.Signature) (oci.Signatures, error) {
   482  	return &replaceOCISignatures{
   483  		Signatures:   signatures,
   484  		attestations: []oci.Signature{o},
   485  	}, nil
   486  }
   487  
   488  type replaceOCISignatures struct {
   489  	oci.Signatures
   490  	attestations []oci.Signature
   491  }
   492  
   493  func (r *replaceOCISignatures) Get() ([]oci.Signature, error) {
   494  	return r.attestations, nil
   495  }
   496  

View as plain text