mirror of
https://github.com/slsa-framework/slsa-verifier.git
synced 2026-05-06 00:26:39 +00:00
better errors
Signed-off-by: Ramon Petgrave <ramon.petgrave64@gmail.com>
This commit is contained in:
@@ -21,7 +21,10 @@ import (
|
||||
// Bundle specific errors.
|
||||
var (
|
||||
ErrorMismatchSignature = errors.New("bundle tlog entry does not match signature")
|
||||
ErrorUnequalSignatures = errors.New("bundle tlog entry and envelope have an unequal number of signatures")
|
||||
ErrorNoSignatures = errors.New("envolope has no signatures")
|
||||
ErrorUnexpectedEntryType = errors.New("unexpected tlog entry type")
|
||||
ErorrParsingEntryBody = errors.New("unexpected layout of the bundle tlog entry body")
|
||||
ErrorMissingCertInBundle = errors.New("missing signing certificate in bundle")
|
||||
ErrorUnexpectedBundleContent = errors.New("expected DSSE bundle content")
|
||||
)
|
||||
@@ -111,6 +114,10 @@ func getLeafCertFromBundle(bundle *bundle_v1.Bundle) (*x509.Certificate, error)
|
||||
// DSSE envelope. It MUST verify that the signatures match to ensure that the
|
||||
// tlog timestamp attests to the signature creation time.
|
||||
func matchRekorEntryWithEnvelope(tlogEntry *v1.TransparencyLogEntry, env *dsselib.Envelope) error {
|
||||
if len(env.Signatures) == 0 {
|
||||
return ErrorNoSignatures
|
||||
}
|
||||
|
||||
kindVersion := tlogEntry.GetKindVersion()
|
||||
|
||||
if kindVersion.Kind == "intoto" && kindVersion.Version == "0.0.2" {
|
||||
@@ -121,7 +128,7 @@ func matchRekorEntryWithEnvelope(tlogEntry *v1.TransparencyLogEntry, env *dsseli
|
||||
return matchRekorEntryWithEnvelopeDSSEv001(tlogEntry, env)
|
||||
}
|
||||
|
||||
return fmt.Errorf("%w: %s: %s", ErrorUnexpectedEntryType, kindVersion.Kind, kindVersion.Version)
|
||||
return fmt.Errorf("%w: wanted either intoto v0.0.2 or dsse v0.0.1, got: %s %s", ErrorUnexpectedEntryType, kindVersion.Kind, kindVersion.Version)
|
||||
}
|
||||
|
||||
// matchRekorEntryWithEnvelopeDSSEv001 handles matchRekorEntryWithEnvelope for the intoto v0.0.1 type version.
|
||||
@@ -130,18 +137,18 @@ func matchRekorEntryWithEnvelopeIntotov002(tlogEntry *v1.TransparencyLogEntry, e
|
||||
var toto models.Intoto
|
||||
var intotoObj models.IntotoV002Schema
|
||||
if err := json.Unmarshal(canonicalBody, &toto); err != nil {
|
||||
return fmt.Errorf("%w: %s", ErrorUnexpectedEntryType, err)
|
||||
return fmt.Errorf("%w: %s", ErorrParsingEntryBody, err)
|
||||
}
|
||||
specMarshal, err := json.Marshal(toto.Spec)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %s", ErrorUnexpectedEntryType, err)
|
||||
return fmt.Errorf("%w: %s", ErorrParsingEntryBody, err)
|
||||
}
|
||||
if err := json.Unmarshal(specMarshal, &intotoObj); err != nil {
|
||||
return fmt.Errorf("%w: %s", ErrorUnexpectedEntryType, err)
|
||||
return fmt.Errorf("%w: %s", ErorrParsingEntryBody, err)
|
||||
}
|
||||
|
||||
if len(env.Signatures) != len(intotoObj.Content.Envelope.Signatures) {
|
||||
return fmt.Errorf("expected %d sigs in canonical body, got %d",
|
||||
return fmt.Errorf("%w: wanted %d, got %d", ErrorUnequalSignatures,
|
||||
len(env.Signatures),
|
||||
len(intotoObj.Content.Envelope.Signatures))
|
||||
}
|
||||
@@ -169,20 +176,20 @@ func matchRekorEntryWithEnvelopeDSSEv001(tlogEntry *v1.TransparencyLogEntry, env
|
||||
canonicalBody := tlogEntry.GetCanonicalizedBody()
|
||||
var dsseObj models.DSSE
|
||||
if err := json.Unmarshal(canonicalBody, &dsseObj); err != nil {
|
||||
return fmt.Errorf("%w: %s", ErrorUnexpectedEntryType, err)
|
||||
return fmt.Errorf("%w: %s", ErorrParsingEntryBody, err)
|
||||
}
|
||||
var dsseSchemaObj models.DSSEV001Schema
|
||||
|
||||
specMarshal, err := json.Marshal(dsseObj.Spec)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %s", ErrorUnexpectedEntryType, err)
|
||||
return fmt.Errorf("%w: %s", ErorrParsingEntryBody, err)
|
||||
}
|
||||
if err := json.Unmarshal(specMarshal, &dsseSchemaObj); err != nil {
|
||||
return fmt.Errorf("%w: %s", ErrorUnexpectedEntryType, err)
|
||||
return fmt.Errorf("%w: %s", ErorrParsingEntryBody, err)
|
||||
}
|
||||
|
||||
if len(env.Signatures) != len(dsseSchemaObj.Signatures) {
|
||||
return fmt.Errorf("expected %d sigs in canonical body, got %d",
|
||||
return fmt.Errorf("%w: wanted %d, got %d", ErrorUnequalSignatures,
|
||||
len(env.Signatures),
|
||||
len(dsseSchemaObj.Signatures))
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@ package gha
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
dsselib "github.com/secure-systems-lab/go-securesystemslib/dsse"
|
||||
rekorpbv1 "github.com/sigstore/protobuf-specs/gen/pb-go/rekor/v1"
|
||||
serrors "github.com/slsa-framework/slsa-verifier/v2/errors"
|
||||
@@ -83,12 +85,60 @@ func Test_verifyBundle(t *testing.T) {
|
||||
func Test_matchRekorEntryWithEnvelope(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
goodDSSEV001Body := []byte(`
|
||||
{
|
||||
"apiVersion": "0.0.1",
|
||||
"kind": "dsse",
|
||||
"spec": {
|
||||
"signatures": [
|
||||
{
|
||||
"signature": "MEUCIHiah7zQLL9LK9m9/0JH3rHIaYlvcus4h84KOdaR3iAlAiEAio+tnbpkW+V+FPYxpuiJBY0MuD43RVX5QmMwk3sgnUE="
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`)
|
||||
goodDSSEV001Sig := "MEUCIHiah7zQLL9LK9m9/0JH3rHIaYlvcus4h84KOdaR3iAlAiEAio+tnbpkW+V+FPYxpuiJBY0MuD43RVX5QmMwk3sgnUE="
|
||||
goodIntotoV002Body := []byte(`
|
||||
{
|
||||
"apiVersion": "0.0.2",
|
||||
"kind": "intoto",
|
||||
"spec": {
|
||||
"content": {
|
||||
"envelope": {
|
||||
"signatures": [
|
||||
{
|
||||
"publicKey": "mypubkey",
|
||||
"sig": "TUVVQ0lRRGVoVlQ0MFRLUDNxWnlVN3BDcXhwMzRyeGt1Wk1ZRTVBWGhBb0x4NTdzdmdJZ0xSa3NCV1hPamUyMCtrKzh4M3ViZkZzNlpxQ2dLNXc3eXlITFB6SC9tcGs9"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
goodIntotoV001Sig := "MEUCIQDehVT40TKP3qZyU7pCqxp34rxkuZMYE5AXhAoLx57svgIgLRksBWXOje20+k+8x3ubfFs6ZqCgK5w7yyHLPzH/mpk="
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
tlog *rekorpbv1.TransparencyLogEntry
|
||||
env *dsselib.Envelope
|
||||
err error
|
||||
}{
|
||||
{
|
||||
name: "failure: no signtures in envelope",
|
||||
tlog: &rekorpbv1.TransparencyLogEntry{
|
||||
KindVersion: &rekorpbv1.KindVersion{
|
||||
Kind: "intoto",
|
||||
Version: "0.0.2",
|
||||
},
|
||||
CanonicalizedBody: goodIntotoV002Body,
|
||||
},
|
||||
env: &dsselib.Envelope{
|
||||
Signatures: []dsselib.Signature{},
|
||||
},
|
||||
err: ErrorNoSignatures,
|
||||
},
|
||||
{
|
||||
name: "success: dsse v0.0.1",
|
||||
tlog: &rekorpbv1.TransparencyLogEntry{
|
||||
@@ -96,24 +146,12 @@ func Test_matchRekorEntryWithEnvelope(t *testing.T) {
|
||||
Kind: "dsse",
|
||||
Version: "0.0.1",
|
||||
},
|
||||
CanonicalizedBody: []byte(`
|
||||
{
|
||||
"apiVersion": "0.0.1",
|
||||
"kind": "dsse",
|
||||
"spec": {
|
||||
"signatures": [
|
||||
{
|
||||
"signature": "MEUCIHiah7zQLL9LK9m9/0JH3rHIaYlvcus4h84KOdaR3iAlAiEAio+tnbpkW+V+FPYxpuiJBY0MuD43RVX5QmMwk3sgnUE="
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`),
|
||||
CanonicalizedBody: goodDSSEV001Body,
|
||||
},
|
||||
env: &dsselib.Envelope{
|
||||
Signatures: []dsselib.Signature{
|
||||
{
|
||||
Sig: "MEUCIHiah7zQLL9LK9m9/0JH3rHIaYlvcus4h84KOdaR3iAlAiEAio+tnbpkW+V+FPYxpuiJBY0MuD43RVX5QmMwk3sgnUE=",
|
||||
Sig: goodDSSEV001Sig,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -126,29 +164,12 @@ func Test_matchRekorEntryWithEnvelope(t *testing.T) {
|
||||
Kind: "intoto",
|
||||
Version: "0.0.2",
|
||||
},
|
||||
CanonicalizedBody: []byte(`
|
||||
{
|
||||
"apiVersion": "0.0.2",
|
||||
"kind": "intoto",
|
||||
"spec": {
|
||||
"content": {
|
||||
"envelope": {
|
||||
"signatures": [
|
||||
{
|
||||
"publicKey": "mypubkey",
|
||||
"sig": "TUVVQ0lRRGVoVlQ0MFRLUDNxWnlVN3BDcXhwMzRyeGt1Wk1ZRTVBWGhBb0x4NTdzdmdJZ0xSa3NCV1hPamUyMCtrKzh4M3ViZkZzNlpxQ2dLNXc3eXlITFB6SC9tcGs9"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
CanonicalizedBody: goodIntotoV002Body,
|
||||
},
|
||||
env: &dsselib.Envelope{
|
||||
Signatures: []dsselib.Signature{
|
||||
{
|
||||
Sig: "MEUCIQDehVT40TKP3qZyU7pCqxp34rxkuZMYE5AXhAoLx57svgIgLRksBWXOje20+k+8x3ubfFs6ZqCgK5w7yyHLPzH/mpk=",
|
||||
Sig: goodIntotoV001Sig,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -161,29 +182,38 @@ func Test_matchRekorEntryWithEnvelope(t *testing.T) {
|
||||
Kind: "dsse",
|
||||
Version: "0.0.1",
|
||||
},
|
||||
CanonicalizedBody: []byte(`
|
||||
{
|
||||
"apiVersion": "0.0.1",
|
||||
"kind": "dsse",
|
||||
"spec": {
|
||||
"signatures": [
|
||||
{
|
||||
"signature": "MEUCIHiah7zQLL9LK9m9/0JH3rHIaYlvcus4h84KOdaR3iAlAiEAio+tnbpkW+V+FPYxpuiJBY0MuD43RVX5QmMwk3sgnUE="
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`),
|
||||
CanonicalizedBody: goodDSSEV001Body,
|
||||
},
|
||||
env: &dsselib.Envelope{
|
||||
Signatures: []dsselib.Signature{
|
||||
{
|
||||
Sig: "d3Jvbmcgc2lnCg==",
|
||||
Sig: base64.StdEncoding.EncodeToString([]byte("mysig")),
|
||||
},
|
||||
},
|
||||
},
|
||||
err: ErrorMismatchSignature,
|
||||
},
|
||||
{
|
||||
name: "faiulure: dsse v0.0.1: unequal number of signatures",
|
||||
tlog: &rekorpbv1.TransparencyLogEntry{
|
||||
KindVersion: &rekorpbv1.KindVersion{
|
||||
Kind: "dsse",
|
||||
Version: "0.0.1",
|
||||
},
|
||||
CanonicalizedBody: goodDSSEV001Body,
|
||||
},
|
||||
env: &dsselib.Envelope{
|
||||
Signatures: []dsselib.Signature{
|
||||
{
|
||||
Sig: base64.StdEncoding.EncodeToString([]byte("mysig")),
|
||||
},
|
||||
{
|
||||
Sig: base64.StdEncoding.EncodeToString([]byte("othersig")),
|
||||
},
|
||||
},
|
||||
},
|
||||
err: ErrorUnequalSignatures,
|
||||
},
|
||||
{
|
||||
name: "faiulure: intoto v0.0.2: mismatch signatures",
|
||||
tlog: &rekorpbv1.TransparencyLogEntry{
|
||||
@@ -191,33 +221,19 @@ func Test_matchRekorEntryWithEnvelope(t *testing.T) {
|
||||
Kind: "intoto",
|
||||
Version: "0.0.2",
|
||||
},
|
||||
CanonicalizedBody: []byte(`
|
||||
{
|
||||
"apiVersion": "0.0.2",
|
||||
"kind": "intoto",
|
||||
"spec": {
|
||||
"content": {
|
||||
"envelope": {
|
||||
"signatures": [
|
||||
{
|
||||
"publicKey": "mypubkey",
|
||||
"sig": "TUVVQ0lRRGVoVlQ0MFRLUDNxWnlVN3BDcXhwMzRyeGt1Wk1ZRTVBWGhBb0x4NTdzdmdJZ0xSa3NCV1hPamUyMCtrKzh4M3ViZkZzNlpxQ2dLNXc3eXlITFB6SC9tcGs9"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
CanonicalizedBody: goodIntotoV002Body,
|
||||
},
|
||||
env: &dsselib.Envelope{
|
||||
Signatures: []dsselib.Signature{
|
||||
{
|
||||
Sig: "d3Jvbmcgc2lnCg==",
|
||||
Sig: base64.StdEncoding.EncodeToString([]byte("mysig")),
|
||||
},
|
||||
{
|
||||
Sig: base64.StdEncoding.EncodeToString([]byte("othersig")),
|
||||
},
|
||||
},
|
||||
},
|
||||
err: ErrorMismatchSignature,
|
||||
err: ErrorUnequalSignatures,
|
||||
},
|
||||
{
|
||||
name: "failure: unknown type",
|
||||
@@ -227,7 +243,13 @@ func Test_matchRekorEntryWithEnvelope(t *testing.T) {
|
||||
Version: "0.0.x",
|
||||
},
|
||||
},
|
||||
env: &dsselib.Envelope{},
|
||||
env: &dsselib.Envelope{
|
||||
Signatures: []dsselib.Signature{
|
||||
{
|
||||
Sig: base64.StdEncoding.EncodeToString([]byte("mysig")),
|
||||
},
|
||||
},
|
||||
},
|
||||
err: ErrorUnexpectedEntryType,
|
||||
},
|
||||
{
|
||||
@@ -238,7 +260,13 @@ func Test_matchRekorEntryWithEnvelope(t *testing.T) {
|
||||
Version: "0.0.x",
|
||||
},
|
||||
},
|
||||
env: &dsselib.Envelope{},
|
||||
env: &dsselib.Envelope{
|
||||
Signatures: []dsselib.Signature{
|
||||
{
|
||||
Sig: base64.StdEncoding.EncodeToString([]byte("mysig")),
|
||||
},
|
||||
},
|
||||
},
|
||||
err: ErrorUnexpectedEntryType,
|
||||
},
|
||||
{
|
||||
@@ -249,9 +277,51 @@ func Test_matchRekorEntryWithEnvelope(t *testing.T) {
|
||||
Version: "0.0.x",
|
||||
},
|
||||
},
|
||||
env: &dsselib.Envelope{},
|
||||
env: &dsselib.Envelope{
|
||||
Signatures: []dsselib.Signature{
|
||||
{
|
||||
Sig: base64.StdEncoding.EncodeToString([]byte("mysig")),
|
||||
},
|
||||
},
|
||||
},
|
||||
err: ErrorUnexpectedEntryType,
|
||||
},
|
||||
{
|
||||
name: "failure: parse error: dsse kind, intoto body",
|
||||
tlog: &rekorpbv1.TransparencyLogEntry{
|
||||
KindVersion: &rekorpbv1.KindVersion{
|
||||
Kind: "dsse",
|
||||
Version: "0.0.1",
|
||||
},
|
||||
CanonicalizedBody: goodIntotoV002Body,
|
||||
},
|
||||
env: &dsselib.Envelope{
|
||||
Signatures: []dsselib.Signature{
|
||||
{
|
||||
Sig: base64.StdEncoding.EncodeToString([]byte("mysig")),
|
||||
},
|
||||
},
|
||||
},
|
||||
err: ErorrParsingEntryBody,
|
||||
},
|
||||
{
|
||||
name: "failure: parse error: intoto kind, dsse body",
|
||||
tlog: &rekorpbv1.TransparencyLogEntry{
|
||||
KindVersion: &rekorpbv1.KindVersion{
|
||||
Kind: "intoto",
|
||||
Version: "0.0.2",
|
||||
},
|
||||
CanonicalizedBody: goodDSSEV001Body,
|
||||
},
|
||||
env: &dsselib.Envelope{
|
||||
Signatures: []dsselib.Signature{
|
||||
{
|
||||
Sig: base64.StdEncoding.EncodeToString([]byte("mysig")),
|
||||
},
|
||||
},
|
||||
},
|
||||
err: ErorrParsingEntryBody,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt // Re-initializing variable so it is not changed while executing the closure below
|
||||
@@ -260,8 +330,8 @@ func Test_matchRekorEntryWithEnvelope(t *testing.T) {
|
||||
|
||||
err := matchRekorEntryWithEnvelope(tt.tlog, tt.env)
|
||||
|
||||
if !errCmp(err, tt.err) {
|
||||
t.Errorf(cmp.Diff(err, tt.err))
|
||||
if errorDiff := cmp.Diff(tt.err, err, cmpopts.EquateErrors()); errorDiff != "" {
|
||||
t.Errorf("unexpected error (-want +got):\n%s", errorDiff)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -267,7 +267,7 @@ func GetValidSignedAttestationWithCert(rClient *rekorGenClient.Rekor,
|
||||
}
|
||||
|
||||
if len(resp.GetPayload()) != 1 {
|
||||
return nil, fmt.Errorf("%w: %s", serrors.ErrorRekorSearch, "no matching rekor entries")
|
||||
return nil, fmt.Errorf("%w: %s", serrors.ErrorRekorSearch, "f")
|
||||
}
|
||||
|
||||
logEntry := resp.Payload[0]
|
||||
|
||||
Reference in New Issue
Block a user