build(gateway): generate deterministic SPDX SBOM
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestBuildSPDXIsDeterministicAndTruthful(t *testing.T) {
|
||||
input := sbomInput{
|
||||
SourceRevision: strings.Repeat("a", 40),
|
||||
Created: time.Date(2026, time.July, 30, 1, 2, 3, 0, time.UTC),
|
||||
ProtocolGoModSum: "h1:protocol-go-mod",
|
||||
Modules: []goModule{
|
||||
{Path: "git.sechmachine.io.vn/sechmachine/VerseVDI-Data-Plane", Version: "(devel)"},
|
||||
{Path: protocolModulePath, Version: "v1.0.0-phase3c-gateway-rc.9", Sum: "h1:protocol"},
|
||||
{Path: "github.com/quic-go/quic-go", Version: "v0.61.0", Sum: "h1:quic"},
|
||||
},
|
||||
Artifacts: []gatewayArtifact{
|
||||
{Architecture: "amd64", Filename: "verse-gateway-linux-amd64", SHA256: strings.Repeat("1", 64), Size: 100},
|
||||
{Architecture: "arm64", Filename: "verse-gateway-linux-arm64", SHA256: strings.Repeat("2", 64), Size: 101},
|
||||
},
|
||||
}
|
||||
first, err := buildSPDX(input)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
second, err := buildSPDX(input)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(first, second) {
|
||||
t.Fatal("SPDX generation was not byte-stable")
|
||||
}
|
||||
text := string(first)
|
||||
for _, required := range []string{
|
||||
`"spdxVersion": "SPDX-2.3"`,
|
||||
input.SourceRevision,
|
||||
"v1.0.0-phase3c-gateway-rc.9",
|
||||
input.ProtocolGoModSum,
|
||||
"verse-gateway-linux-amd64",
|
||||
"verse-gateway-linux-arm64",
|
||||
strings.Repeat("1", 64),
|
||||
strings.Repeat("2", 64),
|
||||
`"licenseConcluded": "NOASSERTION"`,
|
||||
"vulnerability_status=unscanned",
|
||||
"signing_status=unsigned",
|
||||
} {
|
||||
if !strings.Contains(text, required) {
|
||||
t.Fatalf("SPDX is missing %q", required)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildSPDXRejectsAmbiguousInputs(t *testing.T) {
|
||||
valid := sbomInput{
|
||||
SourceRevision: strings.Repeat("a", 40), Created: time.Unix(0, 0).UTC(),
|
||||
ProtocolGoModSum: "h1:protocol-go-mod",
|
||||
Modules: []goModule{
|
||||
{Path: protocolModulePath, Version: "v1.0.0-rc.9", Sum: "h1:protocol"},
|
||||
},
|
||||
Artifacts: []gatewayArtifact{
|
||||
{Architecture: "amd64", Filename: "amd64", SHA256: strings.Repeat("1", 64), Size: 1},
|
||||
{Architecture: "arm64", Filename: "arm64", SHA256: strings.Repeat("2", 64), Size: 1},
|
||||
},
|
||||
}
|
||||
mutations := []func(*sbomInput){
|
||||
func(input *sbomInput) { input.SourceRevision = "short" },
|
||||
func(input *sbomInput) { input.Modules = nil },
|
||||
func(input *sbomInput) { input.Artifacts[1].Architecture = "amd64" },
|
||||
}
|
||||
for index, mutate := range mutations {
|
||||
input := valid
|
||||
input.Modules = append([]goModule(nil), valid.Modules...)
|
||||
input.Artifacts = append([]gatewayArtifact(nil), valid.Artifacts...)
|
||||
mutate(&input)
|
||||
if _, err := buildSPDX(input); err == nil {
|
||||
t.Fatalf("invalid SPDX input %d was accepted", index)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user