110 lines
3.8 KiB
Go
110 lines
3.8 KiB
Go
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
package releaseartifact
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestVerifyNativeReceiptSetRequiresEveryLaneAndMatchingGeneratedOutput(t *testing.T) {
|
|
expected := NativeReceiptExpectation{
|
|
Repository: "gamertan/sandwich-hime",
|
|
Commit: strings.Repeat("a", 40), Tree: strings.Repeat("b", 40),
|
|
}
|
|
directory := nativeReceiptFixture(t, expected, strings.Repeat("c", 64))
|
|
summary, err := VerifyNativeReceiptSet(directory, expected)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if summary.GeneratedDigest != strings.Repeat("c", 64) || len(summary.Lanes) != 4 {
|
|
t.Fatalf("native summary is incomplete: %#v", summary)
|
|
}
|
|
|
|
t.Run("source mismatch", func(t *testing.T) {
|
|
mismatch := expected
|
|
mismatch.Commit = strings.Repeat("d", 40)
|
|
if _, err := VerifyNativeReceiptSet(directory, mismatch); err == nil {
|
|
t.Fatal("mismatched source commit was accepted")
|
|
}
|
|
})
|
|
|
|
t.Run("generated mismatch", func(t *testing.T) {
|
|
mismatched := nativeReceiptFixture(t, expected, strings.Repeat("c", 64))
|
|
lane := requiredNativeLanes[0]
|
|
laneDirectory := filepath.Join(mismatched, lane.directory)
|
|
if err := os.RemoveAll(laneDirectory); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
writeNativeLaneFixture(t, laneDirectory, lane, expected, strings.Repeat("e", 64))
|
|
if _, err := VerifyNativeReceiptSet(mismatched, expected); err == nil {
|
|
t.Fatal("different generated output was accepted")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestVerifyNativeReceiptSetRejectsTamperingAndUnexpectedFiles(t *testing.T) {
|
|
expected := NativeReceiptExpectation{
|
|
Repository: "gamertan/sandwich-hime",
|
|
Commit: strings.Repeat("a", 40), Tree: strings.Repeat("b", 40),
|
|
}
|
|
|
|
t.Run("checksum", func(t *testing.T) {
|
|
directory := nativeReceiptFixture(t, expected, strings.Repeat("c", 64))
|
|
sidecar := filepath.Join(directory, requiredNativeLanes[0].directory, "TEND-CI-VERIFICATION.json.sha256")
|
|
if err := os.Chmod(sidecar, 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(sidecar, []byte(strings.Repeat("0", 64)+" TEND-CI-VERIFICATION.json\n"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := VerifyNativeReceiptSet(directory, expected); err == nil {
|
|
t.Fatal("tampered checksum was accepted")
|
|
}
|
|
})
|
|
|
|
t.Run("unexpected entry", func(t *testing.T) {
|
|
directory := nativeReceiptFixture(t, expected, strings.Repeat("c", 64))
|
|
if err := os.WriteFile(filepath.Join(directory, "notes.txt"), []byte("not a receipt"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := VerifyNativeReceiptSet(directory, expected); err == nil {
|
|
t.Fatal("unexpected native evidence entry was accepted")
|
|
}
|
|
})
|
|
}
|
|
|
|
func nativeReceiptFixture(t *testing.T, expected NativeReceiptExpectation, generatedDigest string) string {
|
|
t.Helper()
|
|
directory := t.TempDir()
|
|
for _, lane := range requiredNativeLanes {
|
|
writeNativeLaneFixture(t, filepath.Join(directory, lane.directory), lane, expected, generatedDigest)
|
|
}
|
|
return directory
|
|
}
|
|
|
|
func writeNativeLaneFixture(t *testing.T, directory string, lane nativeLane, expected NativeReceiptExpectation, generatedDigest string) {
|
|
t.Helper()
|
|
if err := os.Mkdir(directory, 0o700); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
runnerVersion := "v3.1.0"
|
|
if lane.goos == "darwin" {
|
|
runnerVersion = "v3.3.0"
|
|
}
|
|
receipt := Receipt{
|
|
Repository: expected.Repository, Commit: expected.Commit, Tree: expected.Tree,
|
|
GOOS: lane.goos, GOARCH: lane.goarch, GoVersion: lane.goVersion,
|
|
RunnerVersion: runnerVersion, RunnerName: lane.runner,
|
|
GeneratedDigest: generatedDigest, UnsignedArtifactSHA: strings.Repeat("f", 64),
|
|
SuccessfulGates: append([]string(nil), requiredNativeGates...),
|
|
CompletedAt: time.Now().UTC().Add(-time.Minute).Format(time.RFC3339),
|
|
}
|
|
if _, err := WriteReceipt(filepath.Join(directory, "TEND-CI-VERIFICATION.json"), receipt); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|