mirror of
https://github.com/slsa-framework/slsa-verifier.git
synced 2026-05-09 18:16:35 +00:00
535 lines
14 KiB
Go
535 lines
14 KiB
Go
package pkg
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
|
)
|
|
|
|
func provenanceFromBytes(payload []byte) (*intoto.ProvenanceStatement, error) {
|
|
env, err := EnvelopeFromBytes(payload)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return provenanceFromEnv(env)
|
|
}
|
|
|
|
func Test_VerifySha256Subject(t *testing.T) {
|
|
t.Parallel()
|
|
tests := []struct {
|
|
name string
|
|
path string
|
|
artifactHash string
|
|
expected error
|
|
}{
|
|
{
|
|
name: "invalid dsse: not SLSA predicate",
|
|
path: "./testdata/dsse-not-slsa.intoto.jsonl",
|
|
artifactHash: "0ae7e4fa71686538440012ee36a2634dbaa19df2dd16a466f52411fb348bbc4e",
|
|
expected: ErrorInvalidDssePayload,
|
|
},
|
|
{
|
|
name: "invalid dsse: nil subject",
|
|
path: "./testdata/dsse-no-subject.intoto.jsonl",
|
|
artifactHash: "0ae7e4fa71686538440012ee36a2634dbaa19df2dd16a466f52411fb348bbc4e",
|
|
expected: ErrorInvalidDssePayload,
|
|
},
|
|
{
|
|
name: "invalid dsse: no sha256 subject digest",
|
|
path: "./testdata/dsse-no-subject-hash.intoto.jsonl",
|
|
artifactHash: "0ae7e4fa71686538440012ee36a2634dbaa19df2dd16a466f52411fb348bbc4e",
|
|
expected: ErrorInvalidDssePayload,
|
|
},
|
|
{
|
|
name: "mismatched artifact hash with env",
|
|
path: "./testdata/dsse-valid.intoto.jsonl",
|
|
artifactHash: "1ae7e4fa71686538440012ee36a2634dbaa19df2dd16a466f52411fb348bbc4e",
|
|
expected: errorMismatchHash,
|
|
},
|
|
{
|
|
name: "valid entry",
|
|
path: "./testdata/dsse-valid.intoto.jsonl",
|
|
artifactHash: "0ae7e4fa71686538440012ee36a2634dbaa19df2dd16a466f52411fb348bbc4e",
|
|
expected: nil,
|
|
},
|
|
{
|
|
name: "valid entry multiple subjects last entry",
|
|
path: "./testdata/dsse-valid-multi-subjects.intoto.jsonl",
|
|
artifactHash: "03e7e4fa71686538440012ee36a2634dbaa19df2dd16a466f52411fb348bbc4e",
|
|
expected: nil,
|
|
},
|
|
{
|
|
name: "valid multiple subjects second entry",
|
|
path: "./testdata/dsse-valid-multi-subjects.intoto.jsonl",
|
|
artifactHash: "02e7e4fa71686538440012ee36a2634dbaa19df2dd16a466f52411fb348bbc4e",
|
|
expected: nil,
|
|
},
|
|
{
|
|
name: "multiple subjects invalid hash",
|
|
path: "./testdata/dsse-valid-multi-subjects.intoto.jsonl",
|
|
artifactHash: "04e7e4fa71686538440012ee36a2634dbaa19df2dd16a466f52411fb348bbc4e",
|
|
expected: errorMismatchHash,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
tt := tt // Re-initializing variable so it is not changed while executing the closure below
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
content, err := os.ReadFile(tt.path)
|
|
if err != nil {
|
|
panic(fmt.Errorf("os.ReadFile: %w", err))
|
|
}
|
|
prov, err := provenanceFromBytes(content)
|
|
if err != nil {
|
|
panic(fmt.Errorf("provenanceFromBytes: %w", err))
|
|
}
|
|
|
|
err = verifySha256Digest(prov, tt.artifactHash)
|
|
if !errCmp(err, tt.expected) {
|
|
t.Errorf(cmp.Diff(err, tt.expected))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_VerifyBranch(t *testing.T) {
|
|
t.Parallel()
|
|
tests := []struct {
|
|
name string
|
|
path string
|
|
branch string
|
|
expected error
|
|
}{
|
|
{
|
|
name: "ref main",
|
|
path: "./testdata/dsse-main-ref.intoto.jsonl",
|
|
branch: "main",
|
|
},
|
|
{
|
|
name: "ref branch3",
|
|
path: "./testdata/dsse-branch3-ref.intoto.jsonl",
|
|
branch: "branch3",
|
|
},
|
|
{
|
|
name: "invalid ref type",
|
|
path: "./testdata/dsse-invalid-ref-type.intoto.jsonl",
|
|
expected: ErrorInvalidDssePayload,
|
|
},
|
|
{
|
|
name: "tag branch2 push trigger",
|
|
path: "./testdata/dsse-branch2-tag.intoto.jsonl",
|
|
branch: "branch2",
|
|
},
|
|
{
|
|
name: "v10.0.1 release trigger",
|
|
path: "./testdata/dsse-v10.0.1-release.intoto.jsonl",
|
|
branch: "main",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
tt := tt // Re-initializing variable so it is not changed while executing the closure below
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
content, err := os.ReadFile(tt.path)
|
|
if err != nil {
|
|
panic(fmt.Errorf("os.ReadFile: %w", err))
|
|
}
|
|
prov, err := provenanceFromBytes(content)
|
|
if err != nil {
|
|
panic(fmt.Errorf("provenanceFromBytes: %w", err))
|
|
}
|
|
|
|
err = VerifyBranch(prov, tt.branch)
|
|
if !errCmp(err, tt.expected) {
|
|
t.Errorf(cmp.Diff(err, tt.expected))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_VerifyTag(t *testing.T) {
|
|
t.Parallel()
|
|
tests := []struct {
|
|
name string
|
|
path string
|
|
tag string
|
|
expected error
|
|
}{
|
|
{
|
|
name: "ref main",
|
|
path: "./testdata/dsse-main-ref.intoto.jsonl",
|
|
expected: ErrorMismatchTag,
|
|
},
|
|
{
|
|
name: "ref branch3",
|
|
path: "./testdata/dsse-branch3-ref.intoto.jsonl",
|
|
expected: ErrorMismatchTag,
|
|
},
|
|
{
|
|
name: "invalid ref type",
|
|
path: "./testdata/dsse-invalid-ref-type.intoto.jsonl",
|
|
expected: ErrorInvalidDssePayload,
|
|
},
|
|
{
|
|
name: "tag vslsa1",
|
|
path: "./testdata/dsse-vslsa1-tag.intoto.jsonl",
|
|
tag: "vslsa1",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
tt := tt // Re-initializing variable so it is not changed while executing the closure below
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
content, err := os.ReadFile(tt.path)
|
|
if err != nil {
|
|
panic(fmt.Errorf("os.ReadFile: %w", err))
|
|
}
|
|
prov, err := provenanceFromBytes(content)
|
|
if err != nil {
|
|
panic(fmt.Errorf("provenanceFromBytes: %w", err))
|
|
}
|
|
|
|
err = VerifyTag(prov, tt.tag)
|
|
if !errCmp(err, tt.expected) {
|
|
t.Errorf(cmp.Diff(err, tt.expected))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_VerifyVersionedTag(t *testing.T) {
|
|
t.Parallel()
|
|
tests := []struct {
|
|
name string
|
|
path string
|
|
tag string
|
|
expected error
|
|
}{
|
|
{
|
|
name: "ref main",
|
|
path: "./testdata/dsse-main-ref.intoto.jsonl",
|
|
expected: ErrorInvalidSemver,
|
|
tag: "v1.2.3",
|
|
},
|
|
{
|
|
name: "ref branch3",
|
|
path: "./testdata/dsse-branch3-ref.intoto.jsonl",
|
|
expected: ErrorInvalidSemver,
|
|
tag: "v1.2.3",
|
|
},
|
|
{
|
|
name: "tag v1.2 invalid versioning",
|
|
path: "./testdata/dsse-v1.2-tag.intoto.jsonl",
|
|
tag: "1.2",
|
|
expected: ErrorInvalidSemver,
|
|
},
|
|
{
|
|
name: "invalid ref",
|
|
path: "./testdata/dsse-invalid-ref-type.intoto.jsonl",
|
|
expected: ErrorInvalidDssePayload,
|
|
tag: "v1.2.3",
|
|
},
|
|
{
|
|
name: "tag vslsa1 invalid",
|
|
path: "./testdata/dsse-vslsa1-tag.intoto.jsonl",
|
|
tag: "vslsa1",
|
|
expected: ErrorInvalidSemver,
|
|
},
|
|
{
|
|
name: "tag vslsa1 invalid semver",
|
|
path: "./testdata/dsse-vslsa1-tag.intoto.jsonl",
|
|
tag: "v1.2.3",
|
|
expected: ErrorInvalidSemver,
|
|
},
|
|
{
|
|
name: "tag v1.2.3 exact match",
|
|
path: "./testdata/dsse-v1.2.3-tag.intoto.jsonl",
|
|
tag: "v1.2.3",
|
|
},
|
|
{
|
|
name: "tag v1.2.3 match v1.2",
|
|
path: "./testdata/dsse-v1.2.3-tag.intoto.jsonl",
|
|
tag: "v1.2",
|
|
},
|
|
{
|
|
name: "tag v1.2.3 match v1",
|
|
path: "./testdata/dsse-v1.2.3-tag.intoto.jsonl",
|
|
tag: "v1",
|
|
},
|
|
{
|
|
name: "tag v1.2.3 no match v2",
|
|
path: "./testdata/dsse-v1.2.3-tag.intoto.jsonl",
|
|
tag: "v2",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1.2.3 no match v1.3",
|
|
path: "./testdata/dsse-v1.2.3-tag.intoto.jsonl",
|
|
tag: "v1.3",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1.2.3 no match v1.2.4",
|
|
path: "./testdata/dsse-v1.2.3-tag.intoto.jsonl",
|
|
tag: "v1.2.4",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1.2.3 no match v1.2.2",
|
|
path: "./testdata/dsse-v1.2.3-tag.intoto.jsonl",
|
|
tag: "v1.2.2",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1.2 exact v1.2",
|
|
path: "./testdata/dsse-v1.2-tag.intoto.jsonl",
|
|
tag: "v1.2",
|
|
},
|
|
{
|
|
name: "tag v1.2 match v1",
|
|
path: "./testdata/dsse-v1.2-tag.intoto.jsonl",
|
|
tag: "v1",
|
|
},
|
|
{
|
|
name: "tag v1.1 no match v1.3",
|
|
path: "./testdata/dsse-v1.2-tag.intoto.jsonl",
|
|
tag: "v1.1",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v0 no match v1.3",
|
|
path: "./testdata/dsse-v1.2-tag.intoto.jsonl",
|
|
tag: "v0",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1.2 no match v1.3",
|
|
path: "./testdata/dsse-v1.2-tag.intoto.jsonl",
|
|
tag: "v1.3",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1.2 no match v1.2.3",
|
|
path: "./testdata/dsse-v1.2-tag.intoto.jsonl",
|
|
tag: "v1.2.3",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1.2 match v1.2.0",
|
|
path: "./testdata/dsse-v1.2-tag.intoto.jsonl",
|
|
tag: "v1.2.0",
|
|
},
|
|
{
|
|
name: "tag v1.2 match v1.2.0+123",
|
|
path: "./testdata/dsse-v1.2-tag.intoto.jsonl",
|
|
tag: "v1.2.0+123",
|
|
},
|
|
{
|
|
name: "invalid v1.2+123",
|
|
path: "./testdata/dsse-v1.2-tag.intoto.jsonl",
|
|
tag: "v1.2+123",
|
|
expected: ErrorInvalidSemver,
|
|
},
|
|
{
|
|
name: "invalid v1.2-alpha",
|
|
path: "./testdata/dsse-v1.2-tag.intoto.jsonl",
|
|
tag: "v1.2-alpha",
|
|
expected: ErrorInvalidSemver,
|
|
},
|
|
{
|
|
name: "invalid v1-alpha",
|
|
path: "./testdata/dsse-v1.2-tag.intoto.jsonl",
|
|
tag: "v1-alpha",
|
|
expected: ErrorInvalidSemver,
|
|
},
|
|
{
|
|
name: "invalid v1+123",
|
|
path: "./testdata/dsse-v1.2-tag.intoto.jsonl",
|
|
tag: "v1+123",
|
|
expected: ErrorInvalidSemver,
|
|
},
|
|
{
|
|
name: "invalid v1-alpha+123",
|
|
path: "./testdata/dsse-v1.2-tag.intoto.jsonl",
|
|
tag: "v1-alpha+123",
|
|
expected: ErrorInvalidSemver,
|
|
},
|
|
{
|
|
name: "invalid v1.2-alpha+123",
|
|
path: "./testdata/dsse-v1.2-tag.intoto.jsonl",
|
|
tag: "v1.2-alpha+123",
|
|
expected: ErrorInvalidSemver,
|
|
},
|
|
{
|
|
name: "tag v1.2.3-alpha match v1.2.3-alpha",
|
|
path: "./testdata/dsse-v1.2.3-alpha-tag.intoto.jsonl",
|
|
tag: "v1.2.3-alpha",
|
|
},
|
|
{
|
|
name: "tag v1.2.3-alpha no match v1.2.3",
|
|
path: "./testdata/dsse-v1.2.3-alpha-tag.intoto.jsonl",
|
|
tag: "v1.2.3",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1.2.3-alpha+123 match v1.2.3-alpha",
|
|
path: "./testdata/dsse-v1.2.3-alpha+123-tag.intoto.jsonl",
|
|
tag: "v1.2.3-alpha",
|
|
},
|
|
{
|
|
name: "tag v1.2.3-alpha+123 match v1.2.3-alpha+123",
|
|
path: "./testdata/dsse-v1.2.3-alpha+123-tag.intoto.jsonl",
|
|
tag: "v1.2.3-alpha+123",
|
|
},
|
|
{
|
|
name: "tag v1.2.3-alpha+123 match v1.2.3-alpha+456",
|
|
path: "./testdata/dsse-v1.2.3-alpha+123-tag.intoto.jsonl",
|
|
tag: "v1.2.3-alpha+456",
|
|
},
|
|
{
|
|
name: "tag v1.2.3-alpha match v1.2.3-alpha+123",
|
|
path: "./testdata/dsse-v1.2.3-alpha-tag.intoto.jsonl",
|
|
tag: "v1.2.3-alpha+123",
|
|
},
|
|
{
|
|
name: "tag v1.2.3-alpha no match v1.2.3-beta+123",
|
|
path: "./testdata/dsse-v1.2.3-alpha-tag.intoto.jsonl",
|
|
tag: "v1.2.3-beta+123",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1.2.3+123 no match v1.2.3-alpha+123",
|
|
path: "./testdata/dsse-v1.2.3+123-tag.intoto.jsonl",
|
|
tag: "v1.2.3-alpha+123",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1.2.3+123 no match v1.2.3-alpha",
|
|
path: "./testdata/dsse-v1.2.3+123-tag.intoto.jsonl",
|
|
tag: "v1.2.3-alpha",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1.2.3+123 match v1.2.3+123",
|
|
path: "./testdata/dsse-v1.2.3+123-tag.intoto.jsonl",
|
|
tag: "v1.2.3+123",
|
|
},
|
|
{
|
|
name: "tag v1.2.3+123 match v1.2.3",
|
|
path: "./testdata/dsse-v1.2.3+123-tag.intoto.jsonl",
|
|
tag: "v1.2.3",
|
|
},
|
|
{
|
|
name: "tag v1.2.3+123 match v1.2.3+456",
|
|
path: "./testdata/dsse-v1.2.3+123-tag.intoto.jsonl",
|
|
tag: "v1.2.3+456",
|
|
},
|
|
{
|
|
name: "tag v1.2.3 no match v1.2.3-aplha",
|
|
path: "./testdata/dsse-v1.2.3-tag.intoto.jsonl",
|
|
tag: "v1.2.3-alpha",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1.2.3-alpha no match v1.2.3-beta",
|
|
path: "./testdata/dsse-v1.2.3-alpha-tag.intoto.jsonl",
|
|
tag: "v1.2.3-beta",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1.2 no match v1.2.3-beta",
|
|
path: "./testdata/dsse-v1.2.3-alpha-tag.intoto.jsonl",
|
|
tag: "v1.2.3-beta",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1.2.3 match v1.2.3+123",
|
|
path: "./testdata/dsse-v1.2.3-tag.intoto.jsonl",
|
|
tag: "v1.2.3+123",
|
|
},
|
|
{
|
|
name: "tag v1.2 no match v1.2.0-aplha+123",
|
|
path: "./testdata/dsse-v1.2-tag.intoto.jsonl",
|
|
tag: "v1.2.0-alpha+123",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1.2 no match v2",
|
|
path: "./testdata/dsse-v1.2-tag.intoto.jsonl",
|
|
tag: "v2",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1 exact match",
|
|
path: "./testdata/dsse-v1-tag.intoto.jsonl",
|
|
tag: "v1",
|
|
},
|
|
{
|
|
name: "tag v1 no match v2",
|
|
path: "./testdata/dsse-v1-tag.intoto.jsonl",
|
|
tag: "v2",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1 no match v1.2",
|
|
path: "./testdata/dsse-v1-tag.intoto.jsonl",
|
|
tag: "v1.2",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1 no match v0",
|
|
path: "./testdata/dsse-v1-tag.intoto.jsonl",
|
|
tag: "v0",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1 no match v1.2.3",
|
|
path: "./testdata/dsse-v1-tag.intoto.jsonl",
|
|
tag: "v1.2.3",
|
|
expected: ErrorMismatchVersionedTag,
|
|
},
|
|
{
|
|
name: "tag v1 match v1.0",
|
|
path: "./testdata/dsse-v1-tag.intoto.jsonl",
|
|
tag: "v1.0",
|
|
},
|
|
{
|
|
name: "tag v1 match v1.0.0",
|
|
path: "./testdata/dsse-v1-tag.intoto.jsonl",
|
|
tag: "v1.0.0",
|
|
},
|
|
{
|
|
name: "invalid v1-alpha",
|
|
path: "./testdata/dsse-v1-tag.intoto.jsonl",
|
|
tag: "v1-alpha",
|
|
expected: ErrorInvalidSemver,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
tt := tt // Re-initializing variable so it is not changed while executing the closure below
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
content, err := os.ReadFile(tt.path)
|
|
if err != nil {
|
|
panic(fmt.Errorf("os.ReadFile: %w", err))
|
|
}
|
|
prov, err := provenanceFromBytes(content)
|
|
if err != nil {
|
|
panic(fmt.Errorf("provenanceFromBytes: %w", err))
|
|
}
|
|
|
|
err = VerifyVersionedTag(prov, tt.tag)
|
|
if !errCmp(err, tt.expected) {
|
|
t.Errorf(cmp.Diff(err, tt.expected))
|
|
}
|
|
})
|
|
}
|
|
}
|