Skip to content

Commit

Permalink
Add slsa compare options (#887)
Browse files Browse the repository at this point in the history
Prior, the `want` part of some unit tests on slsa provenance requires slice
field to be in particular order to match the `got`.

Now, we introduce compare options to make sure tests are irrelevant to the
order in those slice fields.

Signed-off-by: Chuang Wang <chuangw@google.com>
  • Loading branch information
chuangw6 authored Jul 31, 2023
1 parent 8f1b94f commit 25e7a6c
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 8 deletions.
82 changes: 82 additions & 0 deletions pkg/chains/formats/slsa/internal/compare/slsacompare.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
Copyright 2023 The Tekton 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 compare

import (
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/in-toto/in-toto-golang/in_toto"
"github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common"
slsa "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v1"
)

// SLSAV1CompareOptions returns the comparison options for sorting some slice fields in
// SLSA v1 statement including ResourceDescriptor and Subject.
func SLSAV1CompareOptions() []cmp.Option {
// checking content + uri + digest should be sufficient here based on the fact that
// a ResourceDescriptor MUST specify one of uri, digest or content at a minimum.
// Source: https://github.com/in-toto/attestation/blob/main/spec/v1/resource_descriptor.md#fields
resourceDescriptorSort := func(x, y slsa.ResourceDescriptor) bool {
if string(x.Content) != string(y.Content) {
return string(x.Content) < string(y.Content)
}
if x.URI != y.URI {
return x.URI < y.URI
}
return lessDigestSet(x.Digest, y.Digest)
}

subjectSort := func(x, y in_toto.Subject) bool {
if x.Name != y.Name {
return x.Name < y.Name
}
return lessDigestSet(x.Digest, y.Digest)
}

return []cmp.Option{
cmpopts.SortSlices(resourceDescriptorSort),
cmpopts.SortSlices(subjectSort),
}
}

// MaterialsCompareOption returns the comparison option to sort and compare a
// list of Materials.
func MaterialsCompareOption() cmp.Option {
materialsSort := func(x, y common.ProvenanceMaterial) bool {
if x.URI != y.URI {
return x.URI < y.URI
}
return lessDigestSet(x.Digest, y.Digest)
}
return cmpopts.SortSlices(materialsSort)
}

func lessDigestSet(x, y common.DigestSet) bool {
for algo, digestX := range x {
digestY, ok := y[algo]
if !ok {
// Algorithm not present in y, x is considered greater.
return false
}
// Compare the digests lexicographically.
if digestX != digestY {
return digestX < digestY
}
// The digests are equal, check the next algorithm.
}

// All algorithms in x have corresponding entries in y, so check if y has more algorithms.
return len(x) < len(y)
}
5 changes: 3 additions & 2 deletions pkg/chains/formats/slsa/internal/material/material_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common"
"github.com/tektoncd/chains/internal/backport"
"github.com/tektoncd/chains/pkg/artifacts"
"github.com/tektoncd/chains/pkg/chains/formats/slsa/internal/compare"
"github.com/tektoncd/chains/pkg/chains/objects"
"github.com/tektoncd/chains/pkg/internal/objectloader"
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
Expand Down Expand Up @@ -360,7 +361,7 @@ func TestPipelineMaterials(t *testing.T) {
if err != nil {
t.Error(err)
}
if diff := cmp.Diff(expected, got); diff != "" {
if diff := cmp.Diff(expected, got, compare.MaterialsCompareOption()); diff != "" {
t.Errorf("Materials(): -want +got: %s", diff)
}
}
Expand Down Expand Up @@ -394,7 +395,7 @@ func TestStructuredResultPipelineMaterials(t *testing.T) {
if err != nil {
t.Errorf("error while extracting materials: %v", err)
}
if diff := cmp.Diff(want, got); diff != "" {
if diff := cmp.Diff(want, got, compare.MaterialsCompareOption()); diff != "" {
t.Errorf("materials(): -want +got: %s", diff)
}
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/chains/formats/slsa/v1/intotoite6_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/tektoncd/chains/pkg/artifacts"
"github.com/tektoncd/chains/pkg/chains/formats"
"github.com/tektoncd/chains/pkg/chains/formats/slsa/attest"
"github.com/tektoncd/chains/pkg/chains/formats/slsa/internal/compare"
"github.com/tektoncd/chains/pkg/chains/formats/slsa/v1/pipelinerun"
"github.com/tektoncd/chains/pkg/chains/formats/slsa/v1/taskrun"
"github.com/tektoncd/chains/pkg/chains/objects"
Expand Down Expand Up @@ -365,7 +366,7 @@ func TestPipelineRunCreatePayload(t *testing.T) {
t.Errorf("unexpected error: %s", err.Error())
}
// Sort Materials since their order can vary and result in flakes
if diff := cmp.Diff(expected, got); diff != "" {
if diff := cmp.Diff(expected, got, compare.MaterialsCompareOption()); diff != "" {
t.Errorf("InTotoIte6.CreatePayload(): -want +got: %s", diff)
}
}
Expand Down Expand Up @@ -582,7 +583,7 @@ func TestPipelineRunCreatePayloadChildRefs(t *testing.T) {
t.Errorf("unexpected error: %s", err.Error())
}
// Sort Materials since their order can vary and result in flakes
if diff := cmp.Diff(expected, got); diff != "" {
if diff := cmp.Diff(expected, got, compare.MaterialsCompareOption()); diff != "" {
t.Errorf("InTotoIte6.CreatePayload(): -want +got: %s", diff)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common"
slsa "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v1"

"github.com/tektoncd/chains/pkg/chains/formats/slsa/internal/compare"
"github.com/tektoncd/chains/pkg/chains/formats/slsa/internal/slsaconfig"
"github.com/tektoncd/chains/pkg/chains/objects"
"github.com/tektoncd/chains/pkg/internal/objectloader"
Expand Down Expand Up @@ -356,7 +357,7 @@ func TestGenerateAttestation(t *testing.T) {
if err != nil {
t.Errorf("unwant error: %s", err.Error())
}
if diff := cmp.Diff(want, got); diff != "" {
if diff := cmp.Diff(want, got, compare.SLSAV1CompareOptions()...); diff != "" {
t.Errorf("GenerateAttestation(): -want +got: %s", diff)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
v1 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v1"
"github.com/tektoncd/chains/internal/backport"
"github.com/tektoncd/chains/pkg/artifacts"
"github.com/tektoncd/chains/pkg/chains/formats/slsa/internal/compare"
"github.com/tektoncd/chains/pkg/chains/objects"
"github.com/tektoncd/chains/pkg/internal/objectloader"
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
Expand Down Expand Up @@ -507,7 +508,7 @@ func TestPipelineRun(t *testing.T) {
if err != nil {
t.Error(err)
}
if diff := cmp.Diff(expected, got); diff != "" {
if diff := cmp.Diff(expected, got, compare.SLSAV1CompareOptions()...); diff != "" {
t.Errorf("PipelineRunResolvedDependencies(): -want +got: %s", diff)
}
}
Expand Down Expand Up @@ -542,7 +543,7 @@ func TestPipelineRunStructuredResult(t *testing.T) {
if err != nil {
t.Errorf("error while extracting resolvedDependencies: %v", err)
}
if diff := cmp.Diff(want, got); diff != "" {
if diff := cmp.Diff(want, got, compare.SLSAV1CompareOptions()...); diff != "" {
t.Errorf("resolvedDependencies(): -want +got: %s", diff)
}
}
3 changes: 2 additions & 1 deletion pkg/chains/formats/slsa/v2alpha2/slsav2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"time"

"github.com/tektoncd/chains/pkg/chains/formats"
"github.com/tektoncd/chains/pkg/chains/formats/slsa/internal/compare"
"github.com/tektoncd/chains/pkg/chains/formats/slsa/v2alpha2/internal/pipelinerun"
"github.com/tektoncd/chains/pkg/chains/objects"
"github.com/tektoncd/chains/pkg/config"
Expand Down Expand Up @@ -496,7 +497,7 @@ func TestPipelineRunCreatePayload1(t *testing.T) {
if err != nil {
t.Errorf("unexpected error: %s", err.Error())
}
if diff := cmp.Diff(expected, got); diff != "" {
if diff := cmp.Diff(expected, got, compare.SLSAV1CompareOptions()...); diff != "" {
t.Errorf("Slsa.CreatePayload(): -want +got: %s", diff)
}
}

0 comments on commit 25e7a6c

Please sign in to comment.