mirror of
https://github.com/slsa-framework/slsa-verifier.git
synced 2026-02-14 17:49:58 +00:00
✨ Iterate thru subjects when verifying subject's hash (#112)
* Iterate thru subjects * missing file * update
This commit is contained in:
@@ -23,7 +23,7 @@ You have two options to install the verifier.
|
||||
|
||||
#### Option 1: Install via go
|
||||
```
|
||||
$ go install github.com/slsa-framework/slsa-verifier@v1.1.0
|
||||
$ go install github.com/slsa-framework/slsa-verifier@v1.1.1
|
||||
$ slsa-verifier <options>
|
||||
```
|
||||
|
||||
|
||||
@@ -92,25 +92,34 @@ func intotoEntry(certPem []byte, provenance []byte) (*intotod.V001Entry, error)
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Get SHA256 Subject Digest from the provenance statement.
|
||||
func getSha256Digest(env *dsselib.Envelope) (string, error) {
|
||||
// Verify SHA256 Subject Digest from the provenance statement.
|
||||
func verifySha256Digest(env *dsselib.Envelope, expectedHash string) error {
|
||||
pyld, err := base64.StdEncoding.DecodeString(env.Payload)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("%w: %s", ErrorInvalidDssePayload, "decoding payload")
|
||||
return fmt.Errorf("%w: %s", ErrorInvalidDssePayload, "decoding payload")
|
||||
}
|
||||
prov := &intoto.ProvenanceStatement{}
|
||||
if err := json.Unmarshal([]byte(pyld), prov); err != nil {
|
||||
return "", fmt.Errorf("%w: %s", ErrorInvalidDssePayload, "unmarshalling json")
|
||||
return fmt.Errorf("%w: %s", ErrorInvalidDssePayload, "unmarshalling json")
|
||||
}
|
||||
|
||||
if len(prov.Subject) == 0 {
|
||||
return "", fmt.Errorf("%w: %s", ErrorInvalidDssePayload, "no subjects")
|
||||
return fmt.Errorf("%w: %s", ErrorInvalidDssePayload, "no subjects")
|
||||
}
|
||||
digestSet := prov.Subject[0].Digest
|
||||
hash, exists := digestSet["sha256"]
|
||||
if !exists {
|
||||
return "", fmt.Errorf("%w: %s", ErrorInvalidDssePayload, "no sha256 subject digest")
|
||||
|
||||
for _, subject := range prov.Subject {
|
||||
digestSet := subject.Digest
|
||||
hash, exists := digestSet["sha256"]
|
||||
if !exists {
|
||||
return fmt.Errorf("%w: %s", ErrorInvalidDssePayload, "no sha256 subject digest")
|
||||
}
|
||||
|
||||
if strings.EqualFold(hash, expectedHash) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return hash, nil
|
||||
|
||||
return fmt.Errorf("expected hash '%s' not found: %w", expectedHash, errorMismatchHash)
|
||||
}
|
||||
|
||||
// GetRekorEntries finds all entry UUIDs by the digest of the artifact binary.
|
||||
@@ -182,7 +191,6 @@ func GetRekorEntriesWithCert(rClient *client.Rekor, artifactHash string, provena
|
||||
}
|
||||
if len(certs) != 1 {
|
||||
return nil, nil, fmt.Errorf("error unmarshaling certificate from pem")
|
||||
|
||||
}
|
||||
|
||||
return env, certs[0], nil
|
||||
@@ -558,16 +566,7 @@ func verifyTrustedBuilderRef(id *WorkflowIdentity, ref string) error {
|
||||
}
|
||||
|
||||
func VerifyProvenance(env *dsselib.Envelope, expectedHash string) error {
|
||||
hash, err := getSha256Digest(env)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !strings.EqualFold(hash, expectedHash) {
|
||||
return fmt.Errorf("expected hash '%s', got '%s': %w", expectedHash, hash, errorMismatchHash)
|
||||
}
|
||||
|
||||
return nil
|
||||
return verifySha256Digest(env, expectedHash)
|
||||
}
|
||||
|
||||
func VerifyBranch(env *dsselib.Envelope, expectedBranch string) error {
|
||||
|
||||
@@ -129,11 +129,29 @@ func Test_VerifyProvenance(t *testing.T) {
|
||||
expected: errorMismatchHash,
|
||||
},
|
||||
{
|
||||
name: "valid rekor entries found",
|
||||
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
|
||||
|
||||
10
pkg/testdata/dsse-valid-multi-subjects.intoto.jsonl
vendored
Normal file
10
pkg/testdata/dsse-valid-multi-subjects.intoto.jsonl
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"payloadType": "application/vnd.in-toto+json",
|
||||
"payload": "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGUiOiB7CiAgICAiYnVpbGRUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9BdHRlc3RhdGlvbnMvR2l0SHViQWN0aW9uc1dvcmtmbG93QHYxIiwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL0F0dGVzdGF0aW9ucy9HaXRIdWJIb3N0ZWRBY3Rpb25zQHYxIgogICAgfSwKICAgICJpbnZvY2F0aW9uIjogewogICAgICAiY29uZmlnU291cmNlIjogewogICAgICAgICJkaWdlc3QiOiB7CiAgICAgICAgICAic2hhMSI6ICI0NTA2MjkwZTJlOGZlYjFmMzRiMjdhMDQ0ZjdjYzg2M2M4MzBlZjZiIgogICAgICAgIH0sCiAgICAgICAgImVudHJ5UG9pbnQiOiAiVGVzdCBTTFNBIiwKICAgICAgICAidXJpIjogImdpdCthc3JhYS9zbHNhLW9uLWdpdGh1Yi10ZXN0LmdpdCIKICAgICAgfSwKICAgICAgImVudmlyb25tZW50IjogewogICAgICAgICJhcmNoIjogImFtZDY0IiwKICAgICAgICAiZW52IjogewogICAgICAgICAgIkdJVEhVQl9FVkVOVF9OQU1FIjogIndvcmtmbG93X2Rpc3BhdGNoIiwKICAgICAgICAgICJHSVRIVUJfUlVOX0lEIjogIjE4OTM3OTkyMjAiLAogICAgICAgICAgIkdJVEhVQl9SVU5fTlVNQkVSIjogIjc2IgogICAgICAgIH0KICAgICAgfQogICAgfSwKICAgICJtYXRlcmlhbHMiOiBbCiAgICAgIHsKICAgICAgICAiZGlnZXN0IjogewogICAgICAgICAgInNoYTEiOiAiNDUwNjI5MGUyZThmZWIxZjM0YjI3YTA0NGY3Y2M4NjNjODMwZWY2YiIKICAgICAgICB9LAogICAgICAgICJ1cmkiOiAiZ2l0K2FzcmFhL3Nsc2Etb24tZ2l0aHViLXRlc3QuZ2l0IgogICAgICB9CiAgICBdCiAgfSwKICAicHJlZGljYXRlVHlwZSI6ICJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjAuMiIsCiAgInN1YmplY3QiOiBbCiAgICB7CiAgICAgICJkaWdlc3QiOiB7CiAgICAgICAgInNoYTI1NiI6ICIwMWU3ZTRmYTcxNjg2NTM4NDQwMDEyZWUzNmEyNjM0ZGJhYTE5ZGYyZGQxNmE0NjZmNTI0MTFmYjM0OGJiYzRlIgogICAgICB9LAogICAgICAibmFtZSI6ICJiaW5hcnktbGludXgtYW1kNjQtMSIKICAgIH0sCiAgICB7CiAgICAgICJkaWdlc3QiOiB7CiAgICAgICAgInNoYTI1NiI6ICIwMmU3ZTRmYTcxNjg2NTM4NDQwMDEyZWUzNmEyNjM0ZGJhYTE5ZGYyZGQxNmE0NjZmNTI0MTFmYjM0OGJiYzRlIgogICAgICB9LAogICAgICAibmFtZSI6ICJiaW5hcnktbGludXgtYW1kNjQtMiIKICAgIH0sCiAgICB7CiAgICAgICJkaWdlc3QiOiB7CiAgICAgICAgInNoYTI1NiI6ICIwM2U3ZTRmYTcxNjg2NTM4NDQwMDEyZWUzNmEyNjM0ZGJhYTE5ZGYyZGQxNmE0NjZmNTI0MTFmYjM0OGJiYzRlIgogICAgICB9LAogICAgICAibmFtZSI6ICJiaW5hcnktbGludXgtYW1kNjQtMyIKICAgIH0KICBdCn0K",
|
||||
"signatures": [
|
||||
{
|
||||
"keyid": "",
|
||||
"sig": "MEUCIGIitQ1z1kUQEEaYdGLUtremEsfBzJyGm+Wp2t3PtzSSAiEAiibeJkqt6tTWcxbHNQqUKmtcteyH49NO8U7KiWtu+yc="
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user