1 package in_toto
2
3 import (
4 "errors"
5 "fmt"
6 "io"
7 "os"
8 "path/filepath"
9 "reflect"
10 "runtime"
11 "testing"
12
13 "github.com/secure-systems-lab/go-securesystemslib/dsse"
14 "github.com/stretchr/testify/assert"
15 )
16
17
18 func testOSisWindows() bool {
19 os := runtime.GOOS
20 return os == "windows"
21 }
22
23 func TestRecordArtifact(t *testing.T) {
24
25 result, err := RecordArtifact("foo.tar.gz", []string{"sha256"}, testOSisWindows())
26 expected := map[string]interface{}{
27 "sha256": "52947cb78b91ad01fe81cd6aef42d1f6817e92b9e6936c1e5aabb7c98514f355",
28 }
29 if !reflect.DeepEqual(result, expected) || err != nil {
30 t.Errorf("RecordArtifact returned '(%s, %s)', expected '(%s, nil)'",
31 result, err, expected)
32 }
33
34
35 result, err = RecordArtifact("file-does-not-exist", []string{"sha256"}, testOSisWindows())
36 if !os.IsNotExist(err) {
37 t.Errorf("RecordArtifact returned '(%s, %s)', expected '(nil, %s)'",
38 result, err, os.ErrNotExist)
39 }
40
41 result, err = RecordArtifact("foo.tar.gz", []string{"invalid"}, testOSisWindows())
42 if !errors.Is(err, ErrUnsupportedHashAlgorithm) {
43 t.Errorf("RecordArtifact returned '(%s, %s)', expected '(nil, %s)'", result, err, ErrUnsupportedHashAlgorithm)
44 }
45 }
46
47
48
49 func copy(src, dst string) (int64, error) {
50 sourceFileStat, err := os.Stat(src)
51 if err != nil {
52 return 0, err
53 }
54
55 if !sourceFileStat.Mode().IsRegular() {
56 return 0, fmt.Errorf("%s is not a regular file", src)
57 }
58
59 source, err := os.Open(src)
60 if err != nil {
61 return 0, err
62 }
63 defer source.Close()
64
65 destination, err := os.Create(dst)
66 if err != nil {
67 return 0, err
68 }
69 defer destination.Close()
70 nBytes, err := io.Copy(destination, source)
71 return nBytes, err
72 }
73
74 func TestGitPathSpec(t *testing.T) {
75
76
77 directoriesToBeCreated := []string{
78 "pathSpecTest",
79 "pathSpecTest/alpha",
80 "pathSpecTest/beta",
81 "pathSpecTest/alpha/charlie",
82 }
83 for _, v := range directoriesToBeCreated {
84 if err := os.Mkdir(v, 0700); err != nil {
85 t.Errorf("could not create tmpdir: %s", err)
86 }
87 }
88 filesToBeCreated := map[string]string{
89 "heidi.pub": "pathSpecTest/heidi.pub",
90 "foo.tar.gz": "pathSpecTest/beta/foo.tar.gz",
91 "dan": "pathSpecTest/alpha/charlie/dan",
92 "dan.pub": "pathSpecTest/beta/dan.pub",
93 }
94 for k, v := range filesToBeCreated {
95 _, err := copy(k, v)
96 if err != nil {
97 t.Errorf("could not copy file: %s", err)
98 }
99 }
100
101 expected := map[string]interface{}{}
102
103 result, err := RecordArtifacts([]string{"pathSpecTest"}, []string{"sha256"}, []string{
104 "*.pub",
105 "beta/foo.tar.gz",
106 "alpha/**",
107 }, nil, testOSisWindows(), false)
108 if !reflect.DeepEqual(result, expected) {
109 t.Errorf("RecordArtifacts returned '(%s, %s)', expected '(%s, nil)'",
110 result, err, expected)
111 }
112
113
114 err = os.RemoveAll("pathSpecTest")
115 if err != nil {
116 t.Errorf("could not clean up pathSpecTest directory: %s", err)
117 }
118 }
119
120
121
122
123
124
125 func TestSymlinkToFile(t *testing.T) {
126 if err := os.Symlink("foo.tar.gz", "foo.tar.gz.sym"); err != nil {
127 t.Errorf("could not create a symlink: %s", err)
128 }
129
130 expected := map[string]interface{}{
131 "foo.tar.gz.sym": map[string]interface{}{
132 "sha256": "52947cb78b91ad01fe81cd6aef42d1f6817e92b9e6936c1e5aabb7c98514f355",
133 },
134 }
135 result, err := RecordArtifacts([]string{"foo.tar.gz.sym"}, []string{"sha256"}, nil, nil, testOSisWindows(), false)
136 if !reflect.DeepEqual(result, expected) {
137 t.Errorf("RecordArtifacts returned '(%s, %s)', expected '(%s, nil)'",
138 result, err, expected)
139 }
140
141 if err := os.Remove("foo.tar.gz.sym"); err != nil {
142 t.Errorf("could not remove foo.tar.gz.sym: %s", err)
143 }
144 }
145
146
147
148 func TestIndirectSymlinkCycles(t *testing.T) {
149 if err := os.Mkdir("symTestA", 0700); err != nil {
150 t.Errorf("could not create tmpdir: %s", err)
151 }
152 if err := os.Mkdir("symTestB", 0700); err != nil {
153 t.Errorf("could not create tmpdir: %s", err)
154 }
155
156
157
158 dir, err := os.Getwd()
159 if err != nil {
160 t.Error(err)
161 }
162
163 linkB := filepath.FromSlash("symTestA/linkToB.sym")
164 linkA := filepath.FromSlash("symTestB/linkToA.sym")
165
166 if err := os.Symlink(dir+"/symTestA", linkA); err != nil {
167 t.Errorf("could not create a symlink: %s", err)
168 }
169 if err := os.Symlink(dir+"/symTestB", linkB); err != nil {
170 t.Errorf("could not create a symlink: %s", err)
171 }
172
173
174 _, err = RecordArtifacts([]string{"symTestA/linkToB.sym", "symTestB/linkToA.sym", "foo.tar.gz"}, []string{"sha256"}, nil, nil, testOSisWindows(), true)
175 if !errors.Is(err, ErrSymCycle) {
176 t.Errorf("we expected: %s, we got: %s", ErrSymCycle, err)
177 }
178
179
180 if err := os.Remove("symTestA/linkToB.sym"); err != nil {
181 t.Errorf("could not remove path: %s", err)
182 }
183
184 if err := os.Remove("symTestB/linkToA.sym"); err != nil {
185 t.Errorf("could not remove path: %s", err)
186 }
187
188 if err := os.Remove("symTestA"); err != nil {
189 t.Errorf("could not remove path: %s", err)
190 }
191
192 if err := os.Remove("symTestB"); err != nil {
193 t.Errorf("could not remove path: %s", err)
194 }
195
196 }
197
198
199 func TestSymlinkToFolder(t *testing.T) {
200 if err := os.MkdirAll("symTest/symTest2", 0700); err != nil {
201 t.Errorf("could not create tmpdir: %s", err)
202 }
203
204 if err := os.Symlink("symTest/symTest2", "symTmpfile.sym"); err != nil {
205 t.Errorf("could not create a symlink: %s", err)
206 }
207
208
209
210
211 p := filepath.FromSlash("symTest/symTest2/symTmpfile")
212
213 if err := os.WriteFile(p, []byte("abc"), 0400); err != nil {
214 t.Errorf("could not write symTmpfile: %s", err)
215 }
216
217 result, err := RecordArtifacts([]string{"symTmpfile.sym"}, []string{"sha256"}, nil, nil, testOSisWindows(), true)
218 if err != nil {
219 t.Error(err)
220 }
221
222 expected := map[string]interface{}{
223 filepath.Join("symTmpfile.sym", "symTmpfile"): map[string]interface{}{
224 "sha256": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
225 },
226 }
227
228 if !reflect.DeepEqual(result, expected) {
229 t.Errorf("RecordArtifacts returned '(%s, %s)', expected '(%s, nil)'",
230 result, err, expected)
231 }
232
233
234 if err := os.Remove("symTest/symTest2/symTmpfile"); err != nil {
235 t.Errorf("could not remove path symTest/symTest2/symTmpfile: %s", err)
236 }
237
238 if err := os.Remove("symTmpfile.sym"); err != nil {
239 t.Errorf("could not remove path symTest/symTest2/symTmpfile.sym: %s", err)
240 }
241
242 if err := os.Remove("symTest/symTest2"); err != nil {
243 t.Errorf("could not remove path symTest/symTest2: %s", err)
244 }
245
246 if err := os.Remove("symTest/"); err != nil {
247 t.Errorf("could not remove path symTest: %s", err)
248 }
249 }
250
251
252 func TestSymlinkCycle(t *testing.T) {
253 if err := os.Mkdir("symlinkCycle/", 0700); err != nil {
254 t.Errorf("could not create tmpdir: %s", err)
255 }
256
257
258
259 dir, err := os.Getwd()
260 if err != nil {
261 t.Error(err)
262 }
263
264 if err := os.Symlink(dir+"/symlinkCycle", "symlinkCycle/symCycle.sym"); err != nil {
265 t.Errorf("could not create a symlink: %s", err)
266 }
267
268
269 _, err = RecordArtifacts([]string{"symlinkCycle/symCycle.sym", "foo.tar.gz"}, []string{"sha256"}, nil, nil, testOSisWindows(), true)
270 if !errors.Is(err, ErrSymCycle) {
271 t.Errorf("we expected: %s, we got: %s", ErrSymCycle, err)
272 }
273
274 if err := os.Remove("symlinkCycle/symCycle.sym"); err != nil {
275 t.Errorf("could not remove path symlinkCycle/symCycle.sym: %s", err)
276 }
277
278 if err := os.Remove("symlinkCycle"); err != nil {
279 t.Errorf("could not remove path symlinkCycle: %s", err)
280 }
281 }
282
283 func TestRecordArtifacts(t *testing.T) {
284
285 if err := os.Mkdir("tmpdir", 0700); err != nil {
286 t.Errorf("could not create tmpdir: %s", err)
287 }
288 if err := os.WriteFile("tmpdir/tmpfile", []byte("abc"), 0400); err != nil {
289 t.Errorf("could not write tmpfile: %s", err)
290 }
291 result, err := RecordArtifacts([]string{"foo.tar.gz",
292 "tmpdir/tmpfile"}, []string{"sha256"}, nil, []string{"tmpdir/"}, testOSisWindows(), false)
293 expected := map[string]interface{}{
294 "foo.tar.gz": map[string]interface{}{
295 "sha256": "52947cb78b91ad01fe81cd6aef42d1f6817e92b9e6936c1e5aabb7c98514f355",
296 },
297 "tmpfile": map[string]interface{}{
298 "sha256": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
299 },
300 }
301 if !reflect.DeepEqual(result, expected) {
302 t.Errorf("RecordArtifacts returned '(%s, %s)', expected '(%s, nil)'",
303 result, err, expected)
304 }
305
306 if err := os.WriteFile("tmpdir/foo.tar.gz", []byte("abc"), 0400); err != nil {
307 t.Errorf("could not write tmpfile: %s", err)
308 }
309 _, err = RecordArtifacts([]string{"foo.tar.gz",
310 "tmpdir/foo.tar.gz"}, []string{"sha256"}, nil, []string{"tmpdir/"}, testOSisWindows(), false)
311 if err == nil {
312 t.Error("duplicated path error expected")
313 }
314
315 if err := os.RemoveAll("tmpdir"); err != nil {
316 t.Errorf("could not remove tmpdir: %s", err)
317 }
318
319
320 result, err = RecordArtifacts([]string{"file-does-not-exist"}, []string{"sha256"}, nil, nil, testOSisWindows(), false)
321 if !os.IsNotExist(err) {
322 t.Errorf("RecordArtifacts returned '(%s, %s)', expected '(nil, %s)'",
323 result, err, os.ErrNotExist)
324 }
325 }
326
327 func TestWaitErrToExitCode(t *testing.T) {
328
329
330 parameters := []error{
331 nil,
332 errors.New(""),
333
334 }
335 expected := []int{
336 0,
337 -1,
338
339 }
340
341 for i := 0; i < len(parameters); i++ {
342 result := waitErrToExitCode(parameters[i])
343 if result != expected[i] {
344 t.Errorf("waitErrToExitCode returned %d, expected %d",
345 result, expected[i])
346 }
347 }
348 }
349
350 func TestRunCommand(t *testing.T) {
351
352 parameters := [][]string{
353 {"sh", "-c", "true"},
354 {"sh", "-c", "false"},
355 {"sh", "-c", "printf out"},
356 {"sh", "-c", "printf err >&2"},
357 }
358 expected := []map[string]interface{}{
359 {"return-value": float64(0), "stdout": "", "stderr": ""},
360 {"return-value": float64(1), "stdout": "", "stderr": ""},
361 {"return-value": float64(0), "stdout": "out", "stderr": ""},
362 {"return-value": float64(0), "stdout": "", "stderr": "err"},
363 }
364 for i := 0; i < len(parameters); i++ {
365 result, err := RunCommand(parameters[i], "")
366 if !reflect.DeepEqual(result, expected[i]) || err != nil {
367 t.Errorf("RunCommand returned '(%s, %s)', expected '(%s, nil)'",
368 result, err, expected[i])
369 }
370 }
371
372
373 result, err := RunCommand([]string{"command-does-not-exist"}, "")
374 if result != nil || err == nil {
375 t.Errorf("RunCommand returned '(%s, %s)', expected '(nil, *exec.Error)'",
376 result, err)
377 }
378 }
379
380 func TestRunCommandErrors(t *testing.T) {
381 tables := []struct {
382 CmdArgs []string
383 RunDir string
384 ExpectedError error
385 }{
386 {nil, "", ErrEmptyCommandArgs},
387 {[]string{}, "", ErrEmptyCommandArgs},
388 }
389 for _, table := range tables {
390 _, err := RunCommand(table.CmdArgs, table.RunDir)
391 if !errors.Is(err, ErrEmptyCommandArgs) {
392 t.Errorf("RunCommand did not provoke expected error. Got: %s, want: %s", err, ErrEmptyCommandArgs)
393 }
394 }
395 }
396
397 func TestInTotoRun(t *testing.T) {
398
399 linkName := "Name"
400
401 var validKey Key
402 if err := validKey.LoadKey("carol", "ed25519", []string{"sha256", "sha512"}); err != nil {
403 t.Error(err)
404 }
405
406 tablesCorrect := []struct {
407 materialPaths []string
408 productPaths []string
409 cmdArgs []string
410 key Key
411 hashAlgorithms []string
412 useDSSE bool
413 result Metadata
414 }{
415 {[]string{"alice.pub"}, []string{"foo.tar.gz"}, []string{"sh", "-c", "printf out; printf err >&2"}, validKey, []string{"sha256"}, false, &Metablock{
416 Signed: Link{
417 Name: linkName,
418 Type: "link",
419 Materials: map[string]interface{}{
420 "alice.pub": map[string]interface{}{
421 "sha256": "f051e8b561835b7b2aa7791db7bc72f2613411b0b7d428a0ac33d45b8c518039",
422 },
423 },
424 Products: map[string]interface{}{
425 "foo.tar.gz": map[string]interface{}{
426 "sha256": "52947cb78b91ad01fe81cd6aef42d1f6817e92b9e6936c1e5aabb7c98514f355",
427 },
428 },
429 ByProducts: map[string]interface{}{
430 "return-value": float64(0), "stdout": "out", "stderr": "err",
431 },
432 Command: []string{"sh", "-c", "printf out; printf err >&2"},
433 Environment: map[string]interface{}{},
434 },
435 Signatures: []Signature{{
436 KeyID: "be6371bc627318218191ce0780fd3183cce6c36da02938a477d2e4dfae1804a6",
437 Sig: "71dfec1af747d02f6463d4baf3bb2c1d903c107470be86c12349433f780b1030e5ca36a10ee5c5d74de16344fe16b459154fd2be05a58fb556dff934d6682403",
438 }},
439 },
440 },
441 {[]string{"alice.pub"}, []string{"foo.tar.gz"}, []string{}, validKey, []string{"sha256"}, false, &Metablock{
442 Signed: Link{
443 Name: linkName,
444 Type: "link",
445 Materials: map[string]interface{}{
446 "alice.pub": map[string]interface{}{
447 "sha256": "f051e8b561835b7b2aa7791db7bc72f2613411b0b7d428a0ac33d45b8c518039",
448 },
449 },
450 Products: map[string]interface{}{
451 "foo.tar.gz": map[string]interface{}{
452 "sha256": "52947cb78b91ad01fe81cd6aef42d1f6817e92b9e6936c1e5aabb7c98514f355",
453 },
454 },
455 ByProducts: map[string]interface{}{},
456 Command: []string{},
457 Environment: map[string]interface{}{},
458 },
459 Signatures: []Signature{{
460 KeyID: "be6371bc627318218191ce0780fd3183cce6c36da02938a477d2e4dfae1804a6",
461 Sig: "f4a2d468965d595b4d29615fb2083ef7ac22a948e1530925612d73ba580ce9765d93db7b7ed1b9755d96f13a6a1e858c64693c2f7adcb311afb28cb57fbadc0c",
462 }},
463 },
464 },
465 {[]string{"alice.pub"}, []string{"foo.tar.gz"}, []string{}, validKey, []string{"sha256"}, true, &Envelope{
466 envelope: &dsse.Envelope{
467 Payload: "eyJfdHlwZSI6ImxpbmsiLCJieXByb2R1Y3RzIjp7fSwiY29tbWFuZCI6W10sImVudmlyb25tZW50Ijp7fSwibWF0ZXJpYWxzIjp7ImFsaWNlLnB1YiI6eyJzaGEyNTYiOiJmMDUxZThiNTYxODM1YjdiMmFhNzc5MWRiN2JjNzJmMjYxMzQxMWIwYjdkNDI4YTBhYzMzZDQ1YjhjNTE4MDM5In19LCJuYW1lIjoiTmFtZSIsInByb2R1Y3RzIjp7ImZvby50YXIuZ3oiOnsic2hhMjU2IjoiNTI5NDdjYjc4YjkxYWQwMWZlODFjZDZhZWY0MmQxZjY4MTdlOTJiOWU2OTM2YzFlNWFhYmI3Yzk4NTE0ZjM1NSJ9fX0=",
468 PayloadType: PayloadType,
469 Signatures: []dsse.Signature{{
470 KeyID: "be6371bc627318218191ce0780fd3183cce6c36da02938a477d2e4dfae1804a6",
471 Sig: "XgNp1Q5N/ivFxNyuUNHcjOarMIj3WXZpb00/ZVy2pxdiAeOZYKpJkXPa7wRAM5auuwrVph9TrwoJQuDpJrZaCw==",
472 }},
473 },
474 }},
475 }
476
477 for _, table := range tablesCorrect {
478 result, err := InTotoRun(linkName, "", table.materialPaths, table.productPaths, table.cmdArgs, table.key, table.hashAlgorithms, nil, nil, testOSisWindows(), false, table.useDSSE)
479 if table.useDSSE {
480 assert.Equal(t, table.result.(*Envelope).envelope, result.(*Envelope).envelope, fmt.Sprintf("InTotoRun returned '(%s, %s)', expected '(%s, nil)'", result, err, table.result))
481 } else {
482 assert.True(t, reflect.DeepEqual(result.(*Metablock), table.result.(*Metablock)), fmt.Sprintf("InTotoRun returned '(%s, %s)', expected '(%s, nil)'", result, err, table.result))
483 }
484
485 if result != nil {
486 if err := result.Dump(linkName + ".link"); err != nil {
487 t.Errorf("error while dumping link metablock to file")
488 }
489 loadedResult, err := LoadMetadata(linkName + ".link")
490 if err != nil {
491 t.Errorf("error while loading link metablock from file")
492 }
493 if table.useDSSE {
494 assert.Equal(t, result.(*Envelope).envelope, loadedResult.(*Envelope).envelope, fmt.Sprintf("dump and loading of signed Link failed. Loaded result: '%s', dumped result '%s'", loadedResult, result))
495 } else {
496 assert.True(t, reflect.DeepEqual(loadedResult, result), fmt.Sprintf("dump and loading of signed Link failed. Loaded result: '%s', dumped result '%s'", loadedResult, result))
497 }
498
499 if err := os.Remove(linkName + ".link"); err != nil {
500 t.Errorf("removing created link file failed")
501 }
502 }
503 }
504
505
506 tablesInvalid := []struct {
507 materialPaths []string
508 productPaths []string
509 cmdArgs []string
510 key Key
511 hashAlgorithms []string
512 }{
513 {[]string{"material-does-not-exist"}, []string{""}, []string{"sh", "-c", "printf test"}, Key{}, []string{"sha256"}},
514 {[]string{"demo.layout"}, []string{"product-does-not-exist"}, []string{"sh", "-c", "printf test"}, Key{}, []string{"sha256"}},
515 {[]string{""}, []string{"/invalid-path/"}, []string{"sh", "-c", "printf test"}, Key{}, []string{"sha256"}},
516 {[]string{}, []string{}, []string{"command-does-not-exist"}, Key{}, []string{"sha256"}},
517 {[]string{"demo.layout"}, []string{"foo.tar.gz"}, []string{"sh", "-c", "printf out; printf err >&2"}, Key{
518 KeyID: "this-is-invalid",
519 KeyIDHashAlgorithms: nil,
520 KeyType: "",
521 KeyVal: KeyVal{},
522 Scheme: "",
523 }, []string{"sha256"}},
524 }
525
526 for _, table := range tablesInvalid {
527 result, err := InTotoRun(linkName, "", table.materialPaths, table.productPaths, table.cmdArgs, table.key, table.hashAlgorithms, nil, nil, testOSisWindows(), false, false)
528 if err == nil {
529 t.Errorf("InTotoRun returned '(%s, %s)', expected error",
530 result, err)
531 }
532 }
533 }
534
535 func TestInTotoRecord(t *testing.T) {
536
537 linkName := "Name"
538
539 var validKey Key
540 if err := validKey.LoadKey("carol", "ed25519", []string{"sha256", "sha512"}); err != nil {
541 t.Error(err)
542 }
543
544 tablesCorrect := []struct {
545 materialPaths []string
546 productPaths []string
547 key Key
548 hashAlgorithms []string
549 useDSSE bool
550 startResult Metadata
551 stopResult Metadata
552 }{
553 {[]string{"alice.pub"}, []string{"foo.tar.gz"}, validKey, []string{"sha256"}, false, &Metablock{
554 Signed: Link{
555 Name: linkName,
556 Type: "link",
557 Materials: map[string]interface{}{
558 "alice.pub": map[string]interface{}{
559 "sha256": "f051e8b561835b7b2aa7791db7bc72f2613411b0b7d428a0ac33d45b8c518039",
560 },
561 },
562 Products: map[string]interface{}{},
563 ByProducts: map[string]interface{}{},
564 Command: []string{},
565 Environment: map[string]interface{}{},
566 },
567 Signatures: []Signature{{
568 KeyID: "be6371bc627318218191ce0780fd3183cce6c36da02938a477d2e4dfae1804a6",
569 Sig: "f02db2e08d065840f266df850eaef7cfb5364bbe1808708945eb45373f4757cfe70c86f7ad5e4d5f746d41489410e0407921b4480788cfae5a7d695e3aa62f06",
570 }},
571 }, &Metablock{
572 Signed: Link{
573 Name: linkName,
574 Type: "link",
575 Materials: map[string]interface{}{
576 "alice.pub": map[string]interface{}{
577 "sha256": "f051e8b561835b7b2aa7791db7bc72f2613411b0b7d428a0ac33d45b8c518039",
578 },
579 },
580 Products: map[string]interface{}{
581 "foo.tar.gz": map[string]interface{}{
582 "sha256": "52947cb78b91ad01fe81cd6aef42d1f6817e92b9e6936c1e5aabb7c98514f355",
583 },
584 },
585 ByProducts: map[string]interface{}{},
586 Command: []string{},
587 Environment: map[string]interface{}{},
588 },
589 Signatures: []Signature{{
590 KeyID: "be6371bc627318218191ce0780fd3183cce6c36da02938a477d2e4dfae1804a6",
591 Sig: "f4a2d468965d595b4d29615fb2083ef7ac22a948e1530925612d73ba580ce9765d93db7b7ed1b9755d96f13a6a1e858c64693c2f7adcb311afb28cb57fbadc0c",
592 }},
593 },
594 },
595 {[]string{"alice.pub"}, []string{"foo.tar.gz"}, validKey, []string{"sha256"}, true, &Envelope{
596 envelope: &dsse.Envelope{
597 PayloadType: PayloadType,
598 Payload: "eyJfdHlwZSI6ImxpbmsiLCJieXByb2R1Y3RzIjp7fSwiY29tbWFuZCI6W10sImVudmlyb25tZW50Ijp7fSwibWF0ZXJpYWxzIjp7ImFsaWNlLnB1YiI6eyJzaGEyNTYiOiJmMDUxZThiNTYxODM1YjdiMmFhNzc5MWRiN2JjNzJmMjYxMzQxMWIwYjdkNDI4YTBhYzMzZDQ1YjhjNTE4MDM5In19LCJuYW1lIjoiTmFtZSIsInByb2R1Y3RzIjp7fX0=",
599 Signatures: []dsse.Signature{{
600 KeyID: "be6371bc627318218191ce0780fd3183cce6c36da02938a477d2e4dfae1804a6",
601 Sig: "1u46q3nVmmvqKz/exUviEBPyfRndXwxouG+Jk1GadqKvhyfZv8to//xLPQWC+zy4bPQTicOp1yIBHqFO0bNeBw==",
602 }},
603 },
604 }, &Envelope{
605 envelope: &dsse.Envelope{
606 PayloadType: PayloadType,
607 Payload: "eyJfdHlwZSI6ImxpbmsiLCJieXByb2R1Y3RzIjp7fSwiY29tbWFuZCI6W10sImVudmlyb25tZW50Ijp7fSwibWF0ZXJpYWxzIjp7ImFsaWNlLnB1YiI6eyJzaGEyNTYiOiJmMDUxZThiNTYxODM1YjdiMmFhNzc5MWRiN2JjNzJmMjYxMzQxMWIwYjdkNDI4YTBhYzMzZDQ1YjhjNTE4MDM5In19LCJuYW1lIjoiTmFtZSIsInByb2R1Y3RzIjp7ImZvby50YXIuZ3oiOnsic2hhMjU2IjoiNTI5NDdjYjc4YjkxYWQwMWZlODFjZDZhZWY0MmQxZjY4MTdlOTJiOWU2OTM2YzFlNWFhYmI3Yzk4NTE0ZjM1NSJ9fX0=",
608 Signatures: []dsse.Signature{{
609 KeyID: "be6371bc627318218191ce0780fd3183cce6c36da02938a477d2e4dfae1804a6",
610 Sig: "XgNp1Q5N/ivFxNyuUNHcjOarMIj3WXZpb00/ZVy2pxdiAeOZYKpJkXPa7wRAM5auuwrVph9TrwoJQuDpJrZaCw==",
611 }},
612 },
613 },
614 },
615 }
616
617 for _, table := range tablesCorrect {
618 result, err := InTotoRecordStart(linkName, table.materialPaths, table.key, table.hashAlgorithms, nil, nil, testOSisWindows(), false, table.useDSSE)
619 assert.Nil(t, err, "unexpected error while running record start")
620 if table.useDSSE {
621 assert.Equal(t, table.startResult.(*Envelope).envelope, result.(*Envelope).envelope, "result from record start did not match expected result")
622 } else {
623 assert.Equal(t, table.startResult.(*Metablock), result.(*Metablock), "result from record start did not match expected result")
624 }
625 stopResult, err := InTotoRecordStop(result, table.productPaths, table.key, table.hashAlgorithms, nil, nil, testOSisWindows(), false, table.useDSSE)
626 assert.Nil(t, err, "unexpected error while running record stop")
627 if table.useDSSE {
628 assert.Equal(t, table.stopResult.(*Envelope).envelope, stopResult.(*Envelope).envelope, "result from record stop did not match expected result")
629 } else {
630 assert.Equal(t, table.stopResult.(*Metablock), stopResult.(*Metablock), "result from record stop did not match expected result")
631 }
632 }
633 }
634
635
636 func TestRecordArtifactWithBlobs(t *testing.T) {
637 type args struct {
638 path string
639 hashAlgorithms []string
640 }
641 tests := []struct {
642 name string
643 args args
644 want map[string]interface{}
645 wantErr error
646 }{
647 {
648 name: "test binary blob without line normalization segments",
649 args: args{
650 path: "foo.tar.gz",
651 hashAlgorithms: []string{"sha256", "sha384", "sha512"},
652 },
653 want: map[string]interface{}{"sha256": "52947cb78b91ad01fe81cd6aef42d1f6817e92b9e6936c1e5aabb7c98514f355",
654 "sha384": "ce17464027a7d7c15b15032b404fc76fdbadfa1fa566d7f7747020df2542a293b3098873a98dbbda6e461f7767b8ff6c",
655 "sha512": "bb040966a5a6aefb646909f636f7f99c9e16b684a1f0e83a87dc30c3ab4d9dec2f9b0091d8be74bbc78ba29cb0c2dd027c223579028cf9822b0bccc49d493a6d"},
656 wantErr: nil,
657 },
658 {
659 name: "test binary blob with windows-like line breaks as byte segments",
660 args: args{
661 path: "helloworld",
662 hashAlgorithms: []string{"sha256", "sha384", "sha512"},
663 },
664 want: map[string]interface{}{"sha256": "fd895747460401ca62d81f310538110734ff5401f8ef86c3ab27168598225db8",
665 "sha384": "ddc3ac40ca8d04929e13c42d555a5a6774d35bfac9e2f4cde5847ab3f12f36831faa3baf1b33922b53d288b352ae4b9a",
666 "sha512": "46f0e37e72879843f95ddecc4d511c9ba90241c34b471c2f2caca2784abe185da50ddc5252562b2a911b7cfedafa3e878f0e6b7aa843c136915da5306061e501"},
667 wantErr: nil,
668 },
669 }
670 for _, tt := range tests {
671 t.Run(tt.name, func(t *testing.T) {
672 got, err := RecordArtifact(tt.args.path, tt.args.hashAlgorithms, false)
673 if err != tt.wantErr {
674 t.Errorf("RecordArtifact() error = %v, wantErr %v", err, tt.wantErr)
675 return
676 }
677 if !reflect.DeepEqual(got, tt.want) {
678 t.Errorf("RecordArtifact() got = %v, want %v", got, tt.want)
679 }
680 })
681 }
682 }
683
684
685
686 func TestLineNormalizationFlag(t *testing.T) {
687 type args struct {
688 path string
689 hashAlgorithms []string
690 }
691 tests := []struct {
692 name string
693 args args
694 wantErr error
695 }{
696 {
697 name: "test line normalization with only new line character",
698 args: args{
699 path: "line-ending-linux",
700 hashAlgorithms: []string{"sha256", "sha384", "sha512"},
701 },
702 wantErr: nil,
703 },
704 {
705 name: "test line normalization with carriage return and new line characters",
706 args: args{
707 path: "line-ending-windows",
708 hashAlgorithms: []string{"sha256", "sha384", "sha512"},
709 },
710 wantErr: nil,
711 },
712 {
713 name: "test line normalization with only carriage return character",
714 args: args{
715 path: "line-ending-macos",
716 hashAlgorithms: []string{"sha256", "sha384", "sha512"},
717 },
718 wantErr: nil,
719 },
720 {
721 name: "test line normalization with combination of all of the above",
722 args: args{
723 path: "line-ending-mixed",
724 hashAlgorithms: []string{"sha256", "sha384", "sha512"},
725 },
726 wantErr: nil,
727 },
728 }
729 expected := map[string]interface{}{
730 "sha256": "efb929dfabd55c93796fc61cbf1fe6157445f093167dbee82e8b069842a4fceb",
731 "sha384": "936e88775dfd17c24ed41e3a896dfdf3395707acee1b6f16a52ae144bdcd8611fd17e817f5b75e5a3cf7a1dacf187bae",
732 "sha512": "1d7a485cb2c3cf22c11b4be9afbf1745e053e21a40301d3e8143350d6d2873117c12acef49d4b3650b5262e8a26ffe809b177f968845bd268f26ffd978d314bd",
733 }
734 for _, tt := range tests {
735 t.Run(tt.name, func(t *testing.T) {
736 got, err := RecordArtifact(tt.args.path, tt.args.hashAlgorithms, true)
737 if err != tt.wantErr {
738 t.Errorf("RecordArtifact() error = %v, wantErr %v", err, tt.wantErr)
739 return
740 }
741 if !reflect.DeepEqual(got, expected) {
742 t.Errorf("RecordArtifact() got = %v, want %v", got, expected)
743 }
744 })
745 }
746 }
747
View as plain text