Skip to content

Commit 7de2874

Browse files
committed
refactor in-toto-golang to in-toto/attestation
refactor v0.1/v0.2 slsa predicates with new attestation protos. update parser to use new protobuf types and timestamp handling fix tests and remove obsolete fields from test data
1 parent a5e63d3 commit 7de2874

File tree

5 files changed

+89
-70
lines changed

5 files changed

+89
-70
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ require (
313313
github.com/google/osv-scanner v1.9.2
314314
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
315315
github.com/hashicorp/go-multierror v1.1.1
316-
github.com/in-toto/attestation v1.1.1
316+
github.com/in-toto/attestation v1.1.2
317317
github.com/jedib0t/go-pretty/v6 v6.6.7
318318
github.com/jeremywohl/flatten v1.0.1
319319
github.com/json-iterator/go v1.1.12

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -804,8 +804,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
804804
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
805805
github.com/ianlancetaylor/demangle v0.0.0-20240912202439-0a2b6291aafd h1:EVX1s+XNss9jkRW9K6XGJn2jL2lB1h5H804oKPsxOec=
806806
github.com/ianlancetaylor/demangle v0.0.0-20240912202439-0a2b6291aafd/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
807-
github.com/in-toto/attestation v1.1.1 h1:QD3d+oATQ0dFsWoNh5oT0udQ3tUrOsZZ0Fc3tSgWbzI=
808-
github.com/in-toto/attestation v1.1.1/go.mod h1:Dcq1zVwA2V7Qin8I7rgOi+i837wEf/mOZwRm047Sjys=
807+
github.com/in-toto/attestation v1.1.2 h1:MBFn6lsMq6dptQZJBhalXTcWMb/aJy3V+GX3VYj/V1E=
808+
github.com/in-toto/attestation v1.1.2/go.mod h1:gYFddHMZj3DiQ0b62ltNi1Vj5rC879bTmBbrv9CRHpM=
809809
github.com/in-toto/in-toto-golang v0.9.0 h1:tHny7ac4KgtsfrG6ybU8gVOZux2H8jN05AXJ9EBM1XU=
810810
github.com/in-toto/in-toto-golang v0.9.0/go.mod h1:xsBVrVsHNsB61++S6Dy2vWosKhuA3lUTQd+eF9HdeMo=
811811
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=

internal/testing/testdata/testdata.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -571,15 +571,12 @@ var (
571571
SlsaPredicate: []model.SLSAPredicateInputSpec{
572572
{Key: "slsa.metadata.completeness.environment", Value: "true"},
573573
{Key: "slsa.metadata.buildStartedOn", Value: "2020-08-19T08:38:00Z"},
574-
{Key: "slsa.metadata.completeness.materials", Value: "false"},
575574
{Key: "slsa.buildType", Value: "https://github.com/Attestations/GitHubActionsWorkflow@v1"},
576575
{Key: "slsa.invocation.configSource.entryPoint", Value: "build.yaml:maketgz"},
577576
{Key: "slsa.invocation.configSource.uri", Value: "git+https://github.com/curl/curl-docker@master"},
578-
{Key: "slsa.metadata.reproducible", Value: "false"},
579577
{Key: "slsa.materials.0.uri", Value: "git+https://github.com/curl/curl-docker@master"},
580578
{Key: "slsa.builder.id", Value: "https://github.com/Attestations/GitHubHostedActions@v1"},
581579
{Key: "slsa.invocation.configSource.digest.sha1", Value: "d6525c840a62b398424a78d792f457477135d0cf"},
582-
{Key: "slsa.metadata.completeness.parameters", Value: "false"},
583580
{Key: "slsa.materials.0.digest.sha1", Value: "24279c5185ddc042896e3748f47fa89b48c1c14e"},
584581
{Key: "slsa.materials.1.uri", Value: "github_hosted_vm:ubuntu-18.04:20210123.1"},
585582
{Key: "slsa.materials.1.digest.sha1", Value: "0bcaaa161e719bca41b6d33fc02547c0f97d5397"},

pkg/ingestor/parser/slsa/parser_slsa.go

Lines changed: 56 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,10 @@ import (
2525

2626
jsoniter "github.com/json-iterator/go"
2727

28+
slsa01 "github.com/in-toto/attestation/go/predicates/provenance/v01"
29+
slsa02 "github.com/in-toto/attestation/go/predicates/provenance/v02"
2830
slsa1 "github.com/in-toto/attestation/go/predicates/provenance/v1"
2931
attestationv1 "github.com/in-toto/attestation/go/v1"
30-
scommon "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common"
31-
slsa01 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.1"
32-
slsa02 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2"
3332
"github.com/jeremywohl/flatten"
3433
"google.golang.org/protobuf/encoding/protojson"
3534

@@ -46,6 +45,8 @@ import (
4645
// - An IsOccurence input spec which will generate a predicate for each occurence
4746

4847
const PredicateSLSAProvenancev1 = "https://slsa.dev/provenance/v1"
48+
const PredicateSLSAProvenancev01 = "https://slsa.dev/provenance/v0.1"
49+
const PredicateSLSAProvenancev02 = "https://slsa.dev/provenance/v0.2"
4950

5051
var ErrMetadataNil = errors.New("SLSA Metadata is nil")
5152
var ErrBuilderNil = errors.New("SLSA Builder is nil")
@@ -61,8 +62,8 @@ type slsaEntity struct {
6162
}
6263

6364
type slsaParser struct {
64-
pred01 *slsa01.ProvenancePredicate
65-
pred02 *slsa02.ProvenancePredicate
65+
pred01 *slsa01.Provenance
66+
pred02 *slsa02.Provenance
6667
pred1 *slsa1.Provenance
6768
smt *attestationv1.Statement
6869
subjects []*slsaEntity
@@ -89,7 +90,6 @@ func (s *slsaParser) initializeSLSAParser() {
8990
s.subjects = make([]*slsaEntity, 0)
9091
s.materials = make([]*slsaEntity, 0)
9192
s.bareMaterials = make([]*model.ArtifactInputSpec, 0)
92-
s.bareMaterials = make([]*model.ArtifactInputSpec, 0)
9393
s.builder = nil
9494
s.slsaAttestation = nil
9595
s.identifierStrings = &common.IdentifierStrings{}
@@ -131,12 +131,12 @@ func (s *slsaParser) getSubject() error {
131131

132132
func (s *slsaParser) getMaterials() error {
133133
switch s.smt.PredicateType {
134-
case slsa01.PredicateSLSAProvenance:
135-
if err := s.getMaterials0(s.pred01.Materials); err != nil {
134+
case PredicateSLSAProvenancev01:
135+
if err := s.getMaterials01(s.pred01.Materials); err != nil {
136136
return err
137137
}
138-
case slsa02.PredicateSLSAProvenance:
139-
if err := s.getMaterials0(s.pred02.Materials); err != nil {
138+
case PredicateSLSAProvenancev02:
139+
if err := s.getMaterials02(s.pred02.Materials); err != nil {
140140
return err
141141
}
142142
case PredicateSLSAProvenancev1:
@@ -174,11 +174,24 @@ func (s *slsaParser) getMaterials1(rds []*attestationv1.ResourceDescriptor) erro
174174
return nil
175175
}
176176

177-
func (s *slsaParser) getMaterials0(materials []scommon.ProvenanceMaterial) error {
177+
func (s *slsaParser) getMaterials01(materials []*slsa01.Material) error {
178+
// append dependency nodes for the materials
179+
for _, mat := range materials {
180+
s.identifierStrings.UnclassifiedStrings = append(s.identifierStrings.UnclassifiedStrings, mat.Uri)
181+
se, err := getSlsaEntity("", mat.Uri, mat.Digest)
182+
if err != nil {
183+
return err
184+
}
185+
s.materials = append(s.materials, se)
186+
}
187+
return nil
188+
}
189+
190+
func (s *slsaParser) getMaterials02(materials []*slsa02.Material) error {
178191
// append dependency nodes for the materials
179192
for _, mat := range materials {
180-
s.identifierStrings.UnclassifiedStrings = append(s.identifierStrings.UnclassifiedStrings, mat.URI)
181-
se, err := getSlsaEntity("", mat.URI, mat.Digest)
193+
s.identifierStrings.UnclassifiedStrings = append(s.identifierStrings.UnclassifiedStrings, mat.Uri)
194+
se, err := getSlsaEntity("", mat.Uri, mat.Digest)
182195
if err != nil {
183196
return err
184197
}
@@ -187,7 +200,7 @@ func (s *slsaParser) getMaterials0(materials []scommon.ProvenanceMaterial) error
187200
return nil
188201
}
189202

190-
func getArtifacts(digests scommon.DigestSet) []*model.ArtifactInputSpec {
203+
func getArtifacts(digests map[string]string) []*model.ArtifactInputSpec {
191204
var artifacts []*model.ArtifactInputSpec
192205
for alg, ds := range digests {
193206
artifacts = append(artifacts, &model.ArtifactInputSpec{
@@ -198,7 +211,7 @@ func getArtifacts(digests scommon.DigestSet) []*model.ArtifactInputSpec {
198211
return artifacts
199212
}
200213

201-
func getSlsaEntity(name, uri string, digests scommon.DigestSet) (*slsaEntity, error) {
214+
func getSlsaEntity(name, uri string, digests map[string]string) (*slsaEntity, error) {
202215
artifacts := getArtifacts(digests)
203216
slsa := &slsaEntity{
204217
artifacts: artifacts,
@@ -231,33 +244,39 @@ func getSlsaEntity(name, uri string, digests scommon.DigestSet) (*slsaEntity, er
231244
return nil, fmt.Errorf("%w unable to get Guac Generic Purl, this should not happen", err)
232245
}
233246

234-
func fillSLSA01(inp *model.SLSAInputSpec, pred *slsa01.ProvenancePredicate) error {
235-
inp.BuildType = pred.Recipe.Type
247+
func fillSLSA01(inp *model.SLSAInputSpec, pred *slsa01.Provenance) error {
248+
if pred.Recipe != nil {
249+
inp.BuildType = pred.Recipe.Type
250+
}
236251

237252
if pred.Metadata == nil {
238253
return ErrMetadataNil
239254
}
240255
if pred.Metadata.BuildStartedOn != nil {
241-
inp.StartedOn = pred.Metadata.BuildStartedOn
256+
startTimePB := time.Unix(pred.Metadata.BuildStartedOn.GetSeconds(), int64(pred.Metadata.BuildStartedOn.GetNanos()))
257+
inp.StartedOn = &startTimePB
242258
}
243259
if pred.Metadata.BuildFinishedOn != nil {
244-
inp.FinishedOn = pred.Metadata.BuildFinishedOn
260+
finishTimePB := time.Unix(pred.Metadata.BuildFinishedOn.GetSeconds(), int64(pred.Metadata.BuildFinishedOn.GetNanos()))
261+
inp.FinishedOn = &finishTimePB
245262
}
246263

247264
return nil
248265
}
249266

250-
func fillSLSA02(inp *model.SLSAInputSpec, pred *slsa02.ProvenancePredicate) error {
267+
func fillSLSA02(inp *model.SLSAInputSpec, pred *slsa02.Provenance) error {
251268
inp.BuildType = pred.BuildType
252269

253270
if pred.Metadata == nil {
254271
return ErrMetadataNil
255272
}
256273
if pred.Metadata.BuildStartedOn != nil {
257-
inp.StartedOn = pred.Metadata.BuildStartedOn
274+
startTimePB := time.Unix(pred.Metadata.BuildStartedOn.GetSeconds(), int64(pred.Metadata.BuildStartedOn.GetNanos()))
275+
inp.StartedOn = &startTimePB
258276
}
259277
if pred.Metadata.BuildFinishedOn != nil {
260-
inp.FinishedOn = pred.Metadata.BuildStartedOn
278+
finishTimePB := time.Unix(pred.Metadata.BuildFinishedOn.GetSeconds(), int64(pred.Metadata.BuildFinishedOn.GetNanos()))
279+
inp.FinishedOn = &finishTimePB
261280
}
262281
return nil
263282
}
@@ -272,7 +291,7 @@ func fillSLSA1(inp *model.SLSAInputSpec, pred *slsa1.Provenance) error {
272291
inp.StartedOn = &startTimePB
273292
}
274293
if pred.RunDetails.Metadata.FinishedOn != nil {
275-
finishTimePB := time.Unix(pred.RunDetails.Metadata.StartedOn.GetSeconds(), int64(pred.RunDetails.Metadata.StartedOn.GetNanos()))
294+
finishTimePB := time.Unix(pred.RunDetails.Metadata.FinishedOn.GetSeconds(), int64(pred.RunDetails.Metadata.FinishedOn.GetNanos()))
276295
inp.FinishedOn = &finishTimePB
277296
}
278297
return nil
@@ -286,18 +305,18 @@ func (s *slsaParser) getSLSA() error {
286305
var data []byte
287306
var err error
288307
switch s.smt.PredicateType {
289-
case slsa01.PredicateSLSAProvenance:
308+
case PredicateSLSAProvenancev01:
290309
if err := fillSLSA01(inp, s.pred01); err != nil {
291310
return fmt.Errorf("could not fill SLSA01: %w", err)
292311
}
293-
if data, err = json.Marshal(s.pred01); err != nil {
312+
if data, err = protojson.Marshal(s.pred01); err != nil {
294313
return fmt.Errorf("could not marshal SLSA01: %w", err)
295314
}
296-
case slsa02.PredicateSLSAProvenance:
315+
case PredicateSLSAProvenancev02:
297316
if err := fillSLSA02(inp, s.pred02); err != nil {
298317
return fmt.Errorf("could not fill SLSA02: %w", err)
299318
}
300-
if data, err = json.Marshal(s.pred02); err != nil {
319+
if data, err = protojson.Marshal(s.pred02); err != nil {
301320
return fmt.Errorf("could not marshal SLSA02: %w", err)
302321
}
303322
case PredicateSLSAProvenancev1:
@@ -335,10 +354,10 @@ func (s *slsaParser) getSLSA() error {
335354
func (s *slsaParser) getBuilder() error {
336355
s.builder = &model.BuilderInputSpec{}
337356
switch s.smt.PredicateType {
338-
case slsa01.PredicateSLSAProvenance:
339-
s.builder.Uri = s.pred01.Builder.ID
340-
case slsa02.PredicateSLSAProvenance:
341-
s.builder.Uri = s.pred02.Builder.ID
357+
case PredicateSLSAProvenancev01:
358+
s.builder.Uri = s.pred01.Builder.Id
359+
case PredicateSLSAProvenancev02:
360+
s.builder.Uri = s.pred02.Builder.Id
342361
case PredicateSLSAProvenancev1:
343362
if s.pred1.RunDetails == nil || s.pred1.RunDetails.Builder == nil {
344363
return ErrBuilderNil
@@ -360,14 +379,14 @@ func (s *slsaParser) parseSlsaPredicate(p []byte) error {
360379
}
361380

362381
switch s.smt.PredicateType {
363-
case slsa01.PredicateSLSAProvenance:
364-
s.pred01 = &slsa01.ProvenancePredicate{}
365-
if err := json.Unmarshal(predBytes, s.pred01); err != nil {
382+
case PredicateSLSAProvenancev01:
383+
s.pred01 = &slsa01.Provenance{}
384+
if err := protojson.Unmarshal(predBytes, s.pred01); err != nil {
366385
return fmt.Errorf("Could not unmarshal v0.1 SLSA provenance statement : %w", err)
367386
}
368-
case slsa02.PredicateSLSAProvenance:
369-
s.pred02 = &slsa02.ProvenancePredicate{}
370-
if err := json.Unmarshal(predBytes, s.pred02); err != nil {
387+
case PredicateSLSAProvenancev02:
388+
s.pred02 = &slsa02.Provenance{}
389+
if err := protojson.Unmarshal(predBytes, s.pred02); err != nil {
371390
return fmt.Errorf("Could not unmarshal v0.2 SLSA provenance statement : %w", err)
372391
}
373392
case PredicateSLSAProvenancev1:

pkg/ingestor/parser/slsa/parser_slsa_test.go

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,18 @@ package slsa
1717

1818
import (
1919
"context"
20+
slsa01 "github.com/in-toto/attestation/go/predicates/provenance/v01"
2021
"reflect"
2122
"testing"
2223
"time"
2324

24-
scommon "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common"
25-
slsa01 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.1"
26-
27-
"github.com/in-toto/in-toto-golang/in_toto"
28-
2925
"github.com/google/go-cmp/cmp"
3026
"github.com/guacsec/guac/internal/testing/testdata"
3127
"github.com/guacsec/guac/pkg/assembler"
3228
model "github.com/guacsec/guac/pkg/assembler/clients/generated"
3329
"github.com/guacsec/guac/pkg/handler/processor"
3430
"github.com/guacsec/guac/pkg/logging"
31+
"google.golang.org/protobuf/types/known/timestamppb"
3532
)
3633

3734
func Test_slsaParser(t *testing.T) {
@@ -85,9 +82,11 @@ func Test_slsaParser(t *testing.T) {
8582
func Test_fillSLSA01(t *testing.T) {
8683
startTime := time.Now()
8784
endTime := time.Now()
85+
startTimePB := timestamppb.New(startTime)
86+
endTimePB := timestamppb.New(endTime)
8887
type args struct {
8988
inp *model.SLSAInputSpec
90-
stmt *in_toto.ProvenanceStatementSLSA01
89+
stmt *slsa01.Provenance
9190
}
9291
tests := []struct {
9392
name string
@@ -98,15 +97,13 @@ func Test_fillSLSA01(t *testing.T) {
9897
name: "default",
9998
args: args{
10099
inp: &model.SLSAInputSpec{},
101-
stmt: &in_toto.ProvenanceStatementSLSA01{
102-
Predicate: slsa01.ProvenancePredicate{
103-
Metadata: &slsa01.ProvenanceMetadata{
104-
BuildStartedOn: &startTime,
105-
BuildFinishedOn: &endTime,
106-
},
107-
Recipe: slsa01.ProvenanceRecipe{
108-
Type: "test",
109-
},
100+
stmt: &slsa01.Provenance{
101+
Metadata: &slsa01.Metadata{
102+
BuildStartedOn: startTimePB,
103+
BuildFinishedOn: endTimePB,
104+
},
105+
Recipe: &slsa01.Recipe{
106+
Type: "test",
110107
},
111108
},
112109
},
@@ -115,14 +112,14 @@ func Test_fillSLSA01(t *testing.T) {
115112
name: "stmt predicate metadata is nil",
116113
args: args{
117114
inp: &model.SLSAInputSpec{},
118-
stmt: &in_toto.ProvenanceStatementSLSA01{},
115+
stmt: &slsa01.Provenance{},
119116
},
120117
err: ErrMetadataNil,
121118
},
122119
}
123120
for _, test := range tests {
124121
t.Run(test.name, func(t *testing.T) {
125-
err := fillSLSA01(test.args.inp, &test.args.stmt.Predicate)
122+
err := fillSLSA01(test.args.inp, test.args.stmt)
126123
if err != test.err {
127124
t.Fatalf("fillSLSA01() error = %v, expected error %v", err, test.err)
128125
}
@@ -133,14 +130,20 @@ func Test_fillSLSA01(t *testing.T) {
133130
return
134131
}
135132

136-
if test.args.inp.BuildType != test.args.stmt.Predicate.Recipe.Type {
137-
t.Errorf("fillSLSA01() inp.BuildType not equal to stmt.Predicate.Recipe.Type")
133+
if test.args.inp.BuildType != test.args.stmt.Recipe.Type {
134+
t.Errorf("fillSLSA01() inp.BuildType not equal to stmt.Recipe.Type")
138135
}
139-
if test.args.inp.StartedOn != test.args.stmt.Predicate.Metadata.BuildStartedOn {
140-
t.Errorf("fillSLSA01() inp.BuildStartedOn not equal to stmt.Predicate.Metadata.BuildStartedOn")
136+
if test.args.stmt.Metadata != nil && test.args.stmt.Metadata.BuildStartedOn != nil {
137+
expectedStartTime := time.Unix(test.args.stmt.Metadata.BuildStartedOn.GetSeconds(), int64(test.args.stmt.Metadata.BuildStartedOn.GetNanos()))
138+
if test.args.inp.StartedOn != nil && !test.args.inp.StartedOn.Equal(expectedStartTime) {
139+
t.Errorf("fillSLSA01() inp.StartedOn not equal to expected time")
140+
}
141141
}
142-
if test.args.inp.FinishedOn != test.args.stmt.Predicate.Metadata.BuildFinishedOn {
143-
t.Errorf("fillSLSA01() inp.BuildFinishedOn not equal to stmt.Predicate.Metadata.BuildFinishedOn")
142+
if test.args.stmt.Metadata != nil && test.args.stmt.Metadata.BuildFinishedOn != nil {
143+
expectedFinishTime := time.Unix(test.args.stmt.Metadata.BuildFinishedOn.GetSeconds(), int64(test.args.stmt.Metadata.BuildFinishedOn.GetNanos()))
144+
if test.args.inp.FinishedOn != nil && !test.args.inp.FinishedOn.Equal(expectedFinishTime) {
145+
t.Errorf("fillSLSA01() inp.FinishedOn not equal to expected time")
146+
}
144147
}
145148
})
146149
}
@@ -155,14 +158,14 @@ func Test_getSlsaEntity(t *testing.T) {
155158
testname string
156159
uri string
157160
name string
158-
digest scommon.DigestSet
161+
digest map[string]string
159162
expected *slsaEntity
160163
wantErr bool
161164
}{
162165
{
163166
testname: "with uri and digest",
164167
uri: "pkg:npm/sigstore/[email protected]",
165-
digest: scommon.DigestSet{
168+
digest: map[string]string{
166169
"sha1": "428601801d1f5d105351a403f58c38269de93f680",
167170
},
168171
expected: &slsaEntity{
@@ -188,7 +191,7 @@ func Test_getSlsaEntity(t *testing.T) {
188191
{
189192
testname: "with name and digest",
190193
name: "sigstore",
191-
digest: scommon.DigestSet{
194+
digest: map[string]string{
192195
"sha1": "428601801d1f5d105351a403f58c38269de93f680",
193196
},
194197
expected: &slsaEntity{
@@ -213,7 +216,7 @@ func Test_getSlsaEntity(t *testing.T) {
213216
},
214217
{
215218
testname: "without name and uri",
216-
digest: scommon.DigestSet{
219+
digest: map[string]string{
217220
"sha1": "428601801d1f5d105351a403f58c38269de93f680",
218221
},
219222
wantErr: true,

0 commit comments

Comments
 (0)