Skip to content

Commit

Permalink
Fix field names in generated json statement
Browse files Browse the repository at this point in the history
To keep backwards compatibility with previous struct versions (e.g, github.com/in-toto/in-toto-golang/in_toto) we have to use protojson.Marshal function to transform the struct to its json representation so the tags defined in the intoto.Statement are follow and applied to the resulting string.
  • Loading branch information
renzodavid9 committed Jun 3, 2024
1 parent dc4e8ac commit 9f18493
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 19 deletions.
20 changes: 19 additions & 1 deletion pkg/chains/signing.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"fmt"

"github.com/hashicorp/go-multierror"
intoto "github.com/in-toto/attestation/go/v1"
"github.com/tektoncd/chains/pkg/artifacts"
"github.com/tektoncd/chains/pkg/chains/formats"
"github.com/tektoncd/chains/pkg/chains/objects"
Expand All @@ -29,6 +30,7 @@ import (
"github.com/tektoncd/chains/pkg/chains/storage"
"github.com/tektoncd/chains/pkg/config"
versioned "github.com/tektoncd/pipeline/pkg/client/clientset/versioned"
"google.golang.org/protobuf/encoding/protojson"
"k8s.io/apimachinery/pkg/util/sets"
"knative.dev/pkg/logging"
)
Expand Down Expand Up @@ -169,7 +171,7 @@ func (o *ObjectSigner) Sign(ctx context.Context, tektonObj objects.TektonObject)
}

logger.Infof("Signing object with %s", signerType)
rawPayload, err := json.Marshal(payload)
rawPayload, err := getRawPayload(payload)
if err != nil {
logger.Warnf("Unable to marshal payload: %v", signerType, obj)
continue
Expand Down Expand Up @@ -248,3 +250,19 @@ func HandleRetry(ctx context.Context, obj objects.TektonObject, ps versioned.Int
}
return MarkFailed(ctx, obj, ps, annotations)
}

// getRawPayload returns the payload as a json string. If the given payload is a intoto.Statement type, protojson.Marshal
// is used to get the proper labels/field names in the resulting json.
func getRawPayload(payload interface{}) ([]byte, error) {
switch payloadObj := payload.(type) {
case intoto.Statement:
return protojson.Marshal(&payloadObj)
case *intoto.Statement:
if payloadObj == nil {
return json.Marshal(payload)
}
return protojson.Marshal(payloadObj)
default:
return json.Marshal(payload)
}
}
82 changes: 82 additions & 0 deletions pkg/chains/signing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@ limitations under the License.
package chains

import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"reflect"
"testing"

"github.com/google/go-cmp/cmp"
intoto "github.com/in-toto/attestation/go/v1"
"github.com/sigstore/rekor/pkg/generated/models"
"github.com/tektoncd/chains/pkg/chains/objects"
"github.com/tektoncd/chains/pkg/chains/signing"
Expand Down Expand Up @@ -405,6 +409,84 @@ func TestSigningObjects(t *testing.T) {
}
}

func TestGetRawPayload(t *testing.T) {
tests := []struct {
name string
payload interface{}
expected string
}{
{
name: "intoto.Statement object",
payload: intoto.Statement{
Type: "type1",
PredicateType: "predicate-type1",
},
expected: compactJSON(t, []byte(`{"_type":"type1","predicateType":"predicate-type1"}`)),
},
{
name: "*intoto.Statement object",
payload: &intoto.Statement{
Type: "type1",
PredicateType: "predicate-type1",
},
expected: compactJSON(t, []byte(`{"_type":"type1","predicateType":"predicate-type1"}`)),
},
{
name: "*intoto.Statement object - nil",
payload: (func() *intoto.Statement { return nil })(),
expected: "null",
},
{
name: "other object - nil",
payload: nil,
expected: "null",
},
{
name: "other object with value",
payload: struct {
Name string
ID int
Inner any
}{
Name: "wrapper",
ID: 1,
Inner: struct {
InnerID int
Description string
IsArtifact bool
}{
InnerID: 2,
Description: "some description",
IsArtifact: true,
},
},
expected: compactJSON(t, []byte(`{"Name":"wrapper","ID":1,"Inner": {"InnerID":2,"Description":"some description","IsArtifact":true}}`)),
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
got, err := getRawPayload(test.payload)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
compactExpected := compactJSON(t, got)
if diff := cmp.Diff(test.expected, compactExpected); diff != "" {
t.Errorf("getRawPayload(), -want +got, diff = %s", diff)
}
})
}
}

func compactJSON(t *testing.T, jsonString []byte) string {
t.Helper()
dst := &bytes.Buffer{}
if err := json.Compact(dst, jsonString); err != nil {
t.Fatalf("error getting compact JSON: %v", err)
}
return dst.String()
}

func fakeAllBackends(backends []*mockBackend) map[string]storage.Backend {
newBackends := map[string]storage.Backend{}
for _, m := range backends {
Expand Down
4 changes: 2 additions & 2 deletions test/testdata/slsa/v1/pipeline-output-image.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"type": "https://in-toto.io/Statement/v0.1",
"predicate_type": "https://slsa.dev/provenance/v0.2",
"_type": "https://in-toto.io/Statement/v0.1",
"predicateType": "https://slsa.dev/provenance/v0.2",
"subject": [
{
"name": "gcr.io/foo/bar",
Expand Down
4 changes: 2 additions & 2 deletions test/testdata/slsa/v1/task-output-image.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"type": "https://in-toto.io/Statement/v0.1",
"predicate_type": "https://slsa.dev/provenance/v0.2",
"_type": "https://in-toto.io/Statement/v0.1",
"predicateType": "https://slsa.dev/provenance/v0.2",
"subject": [
{
"name": "gcr.io/foo/bar",
Expand Down
4 changes: 2 additions & 2 deletions test/testdata/slsa/v2/task-output-image.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"type": "https://in-toto.io/Statement/v0.1",
"predicate_type": "https://slsa.dev/provenance/v0.2",
"_type": "https://in-toto.io/Statement/v0.1",
"predicateType": "https://slsa.dev/provenance/v0.2",
"subject": [
{
"name": "gcr.io/foo/bar",
Expand Down
4 changes: 2 additions & 2 deletions test/testdata/slsa/v2alpha3/pipeline-output-image.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"type": "https://in-toto.io/Statement/v1",
"predicate_type": "https://slsa.dev/provenance/v1",
"_type": "https://in-toto.io/Statement/v1",
"predicateType": "https://slsa.dev/provenance/v1",
"subject": [
{
"name": "gcr.io/foo/bar",
Expand Down
4 changes: 2 additions & 2 deletions test/testdata/slsa/v2alpha3/task-output-image.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"type": "https://in-toto.io/Statement/v1",
"predicate_type": "https://slsa.dev/provenance/v1",
"_type": "https://in-toto.io/Statement/v1",
"predicateType": "https://slsa.dev/provenance/v1",
"subject": [
{
"name": "gcr.io/foo/bar",
Expand Down
4 changes: 2 additions & 2 deletions test/testdata/slsa/v2alpha4/pipeline-output-image.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"type": "https://in-toto.io/Statement/v1",
"predicate_type": "https://slsa.dev/provenance/v1",
"_type": "https://in-toto.io/Statement/v1",
"predicateType": "https://slsa.dev/provenance/v1",
"subject": [
{
"name": "gcr.io/foo/bar",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"type": "https://in-toto.io/Statement/v1",
"predicate_type": "https://slsa.dev/provenance/v1",
"_type": "https://in-toto.io/Statement/v1",
"predicateType": "https://slsa.dev/provenance/v1",
"subject": [
{
"name": "gcr.io/foo/img1",
Expand Down
4 changes: 2 additions & 2 deletions test/testdata/slsa/v2alpha4/task-output-image.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"type": "https://in-toto.io/Statement/v1",
"predicate_type": "https://slsa.dev/provenance/v1",
"_type": "https://in-toto.io/Statement/v1",
"predicateType": "https://slsa.dev/provenance/v1",
"subject": [
{
"name": "gcr.io/foo/bar",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"type": "https://in-toto.io/Statement/v1",
"predicate_type": "https://slsa.dev/provenance/v1",
"_type": "https://in-toto.io/Statement/v1",
"predicateType": "https://slsa.dev/provenance/v1",
"subject": [
{
"name": "gcr.io/foo/img2",
Expand Down

0 comments on commit 9f18493

Please sign in to comment.