Skip to content
This repository has been archived by the owner on Apr 9, 2024. It is now read-only.

Commit

Permalink
Fix validation against amber provenance (#143)
Browse files Browse the repository at this point in the history
* Fix tests and the dependency to the schema for the amber provenances
* Fix linting
* Fix test size
  • Loading branch information
rbehjati authored Oct 20, 2022
1 parent 3c1b88c commit 838ea59
Show file tree
Hide file tree
Showing 11 changed files with 47 additions and 88 deletions.
1 change: 0 additions & 1 deletion internal/common/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ go_test(
srcs = ["common_test.go"],
data = [
"//schema/amber-slsa-buildtype/v1:example.json",
"//schema/amber-slsa-buildtype/v1:provenance.json",
"//testdata:build.toml",
"//testdata:provenance.json",
"//testdata:static.txt",
Expand Down
14 changes: 3 additions & 11 deletions internal/common/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package common

import (
"fmt"
"os"
"path/filepath"
"testing"

Expand All @@ -27,7 +26,7 @@ import (

const (
testdataPath = "../../testdata/"
provenanceExamplePath = "testdata/provenance.json"
provenanceExamplePath = "provenance.json"
wantTOMLHash = "322527c0260e25f0e9a2595bd0d71a52294fe2397a7af76165190fd98de8920d"
wantBuilderImageID = "6e5beabe4ace0e3aaa01ce497f5f1ef30fed7c18c596f35621751176b1ab583d"
wantSHA1HexDigitLength = 40
Expand Down Expand Up @@ -55,16 +54,9 @@ func TestLoadBuildConfigFromFile(t *testing.T) {
}

func TestLoadBuildConfigFromProvenance(t *testing.T) {
// The path to provenance is specified relative to the root of the repo, so we need to go one level up.
// Get the current directory before that to restore the path at the end of the test.
currentDir, err := os.Getwd()
if err != nil {
t.Fatalf("couldn't get current directory: %v", err)
}
defer testutil.Chdir(t, currentDir)
testutil.Chdir(t, "../../")
path := filepath.Join(testdataPath, provenanceExamplePath)

provenance, err := amber.ParseProvenanceFile(provenanceExamplePath)
provenance, err := amber.ParseProvenanceFile(path)
if err != nil {
t.Fatalf("couldn't parse the provenance file: %v", err)
}
Expand Down
7 changes: 0 additions & 7 deletions internal/testutil/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,9 @@
package testutil

import (
"os"
"testing"
)

func Chdir(t *testing.T, dir string) {
if err := os.Chdir(dir); err != nil {
t.Fatalf("couldn't change directory to %s: %v", dir, err)
}
}

func AssertEq[T comparable](t *testing.T, name string, got, want T) {
if got != want {
t.Errorf("Unexpected %s: got %v, want %v", name, got, want)
Expand Down
3 changes: 1 addition & 2 deletions internal/verifier/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,10 @@ go_library(

go_test(
name = "verifier_test",
size = "enormous",
size = "small",
srcs = ["verifier_test.go"],
data = [
"//schema/amber-slsa-buildtype/v1:example.json",
"//schema/amber-slsa-buildtype/v1:provenance.json",
"//testdata:provenance.json",
"//testdata:bad_command_provenance.json",
"//testdata:invalid_hash_provenance.json",
Expand Down
16 changes: 16 additions & 0 deletions internal/verifier/verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ package verify

import (
"fmt"
"log"
"os"

slsa "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2"
"github.com/project-oak/transparent-release/internal/common"
Expand Down Expand Up @@ -45,6 +47,14 @@ type ReproducibleProvenanceVerifier struct {
// different returns an error, otherwise returns nil.
// TODO(#126): Refactor and separate verification logic from the logic for reading the file.
func (verifier *ReproducibleProvenanceVerifier) Verify(provenanceFilePath string) error {
// Below we change directory to the root of the Git repo. We have to change directory back to
// the current directory when we are done.
currentDir, err := os.Getwd()
if err != nil {
return fmt.Errorf("couldn't get current directory: %v", err)
}
defer chdir(currentDir)

provenance, err := amber.ParseProvenanceFile(provenanceFilePath)
if err != nil {
return fmt.Errorf("couldn't load the provenance file from %s: %v", provenanceFilePath, err)
Expand Down Expand Up @@ -78,6 +88,12 @@ func (verifier *ReproducibleProvenanceVerifier) Verify(provenanceFilePath string
return nil
}

func chdir(dir string) {
if err := os.Chdir(dir); err != nil {
log.Printf("Couldn't change directory to %s: %v", dir, err)
}
}

// AmberProvenanceMetadataVerifier verifies Amber provenances by comparing the
// content of the provenance predicate against a given set of expected values.
type AmberProvenanceMetadataVerifier struct {
Expand Down
61 changes: 19 additions & 42 deletions internal/verifier/verifier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,83 +15,60 @@
package verify

import (
"os"
"path/filepath"
"strings"
"testing"

"github.com/project-oak/transparent-release/internal/testutil"
)

const validProvenancePath = "testdata/provenance.json"
const invalidHashProvenancePath = "testdata/invalid_hash_provenance.json"
const badCommandProvenancePath = "testdata/bad_command_provenance.json"
const (
testdataPath = "../../testdata/"
validProvenancePath = "provenance.json"
invalidHashProvenancePath = "invalid_hash_provenance.json"
badCommandProvenancePath = "bad_command_provenance.json"
)

func TestReproducibleProvenanceVerifier_validProvenance(t *testing.T) {
// The path to provenance is specified relative to the root of the repo, so we need to go one level up.
// Get the current directory before that to restore the path at the end of the test.
currentDir, err := os.Getwd()
if err != nil {
t.Fatalf("couldn't get current directory: %v", err)
}
defer testutil.Chdir(t, currentDir)
testutil.Chdir(t, "../../")
path := filepath.Join(testdataPath, validProvenancePath)

verifier := ReproducibleProvenanceVerifier{}

if err := verifier.Verify(validProvenancePath); err != nil {
if err := verifier.Verify(path); err != nil {
t.Fatalf("couldn't verify the provenance file: %v", err)
}
}

// TODO(#126): Update the test once Verify is refactored.
func TestReproducibleProvenanceVerifier_invalidHash(t *testing.T) {
// The path to provenance is specified relative to the root of the repo, so we need to go one level up.
// Get the current directory before that to restore the path at the end of the test.
currentDir, err := os.Getwd()
if err != nil {
t.Fatalf("couldn't get current directory: %v", err)
}
defer testutil.Chdir(t, currentDir)
testutil.Chdir(t, "../../")
path := filepath.Join(testdataPath, invalidHashProvenancePath)

verifier := ReproducibleProvenanceVerifier{}

want := "failed to verify the hash of the built binary"

if got := verifier.Verify(invalidHashProvenancePath); !strings.Contains(got.Error(), want) {
if got := verifier.Verify(path); !strings.Contains(got.Error(), want) {
t.Fatalf("got %v, want error message containing %q,", got, want)
}
}

// TODO(#126): Update the test once Verify is refactored.
func TestReproducibleProvenanceVerifier_badCommand(t *testing.T) {
// The path to provenance is specified relative to the root of the repo, so we need to go one level up.
// Get the current directory before that to restore the path at the end of the test.
currentDir, err := os.Getwd()
if err != nil {
t.Fatalf("couldn't get current directory: %v", err)
}
defer testutil.Chdir(t, currentDir)
testutil.Chdir(t, "../../")
path := filepath.Join(testdataPath, badCommandProvenancePath)

verifier := ReproducibleProvenanceVerifier{}

want := "couldn't build the binary"

if got := verifier.Verify(badCommandProvenancePath); !strings.Contains(got.Error(), want) {
if got := verifier.Verify(path); !strings.Contains(got.Error(), want) {
t.Fatalf("got %v, want error message containing %q,", got, want)
}
}

func TestAmberProvenanceMetadataVerifier(t *testing.T) {
// The path to provenance is specified relative to the root of the repo, so we need to go one level up.
// Get the current directory before that to restore the path at the end of the test.
currentDir, err := os.Getwd()
if err != nil {
t.Fatalf("couldn't get current directory: %v", err)
}
defer testutil.Chdir(t, currentDir)
testutil.Chdir(t, "../../")
path := filepath.Join(testdataPath, validProvenancePath)

verifier := AmberProvenanceMetadataVerifier{}

if err := verifier.Verify(validProvenancePath); err != nil {
if err := verifier.Verify(path); err != nil {
t.Fatalf("couldn't verify the provenance file: %v", err)
}
}
5 changes: 1 addition & 4 deletions pkg/amber/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ go_library(
"endorsement.go",
"provenance.go",
],
data = [
"//schema/amber-slsa-buildtype/v1:provenance.json",
],
embedsrcs = ["schema/v1/provenance.json"],
importpath = "github.com/project-oak/transparent-release/pkg/amber",
deps = [
"@com_github_in_toto_in_toto_golang//in_toto:go_default_library",
Expand All @@ -43,7 +41,6 @@ go_test(
data = [
"//schema/amber-claim/v1:example.json",
"//schema/amber-slsa-buildtype/v1:example.json",
"//schema/amber-slsa-buildtype/v1:provenance.json",
],
embed = [":amber"],
deps = [
Expand Down
15 changes: 6 additions & 9 deletions pkg/amber/provenance.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,18 @@ import (
intoto "github.com/in-toto/in-toto-golang/in_toto"
slsa "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2"
"github.com/xeipuuv/gojsonschema"

_ "embed"
)

const (
// AmberBuildTypeV1 is the SLSA BuildType for Amber builds.
AmberBuildTypeV1 = "https://github.com/project-oak/transparent-release/schema/amber-slsa-buildtype/v1/provenance.json"

// SchemaPath is the path to Amber SLSA buildType schema.
SchemaPath = "schema/amber-slsa-buildtype/v1/provenance.json"
)

//go:embed schema/v1/provenance.json
var schema []byte

// BuildConfig represents the BuildConfig in the SLSA Provenance predicate. See the corresponding
// JSON key in the Amber buildType schema.
type BuildConfig struct {
Expand Down Expand Up @@ -83,12 +85,7 @@ func (p *ValidatedProvenance) GetBinaryName() string {
}

func validateSLSAProvenanceJSON(provenanceFile []byte) error {
schemaFile, err := os.ReadFile(SchemaPath)
if err != nil {
return err
}

schemaLoader := gojsonschema.NewStringLoader(string(schemaFile))
schemaLoader := gojsonschema.NewStringLoader(string(schema))
provenanceLoader := gojsonschema.NewStringLoader(string(provenanceFile))

result, err := gojsonschema.Validate(schemaLoader, provenanceLoader)
Expand Down
12 changes: 1 addition & 11 deletions pkg/amber/provenance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,19 @@ package amber

import (
"fmt"
"os"
"testing"

slsa "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2"
"github.com/project-oak/transparent-release/internal/testutil"
)

const (
provenanceExamplePath = "schema/amber-slsa-buildtype/v1/example.json"
provenanceExamplePath = "../../schema/amber-slsa-buildtype/v1/example.json"
wantSHA1HexDigitLength = 40
wantSHA256HexDigitLength = 64
)

func TestExampleProvenance(t *testing.T) {
// The path to provenance is specified relative to the root of the repo, so we need to go one level up.
// Get the current directory before that to restore the path at the end of the test.
currentDir, err := os.Getwd()
if err != nil {
t.Fatalf("couldn't get current directory: %v", err)
}
defer testutil.Chdir(t, currentDir)
testutil.Chdir(t, "../../")

// Parses the provenance and validates it against the schema.
validatedProvenance, err := ParseProvenanceFile(provenanceExamplePath)
if err != nil {
Expand Down
1 change: 0 additions & 1 deletion schema/amber-slsa-buildtype/v1/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,5 @@ package(default_visibility = ["//:__subpackages__"])
licenses(["notice"])

exports_files([
"provenance.json",
"example.json",
])

0 comments on commit 838ea59

Please sign in to comment.