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

Commit

Permalink
Refactor package common (#226)
Browse files Browse the repository at this point in the history
* Move everything related to verification to internal/verification package
* Rename package common to model
* Update README
* Update license file
  • Loading branch information
rbehjati committed Apr 27, 2023
1 parent 060a7b2 commit d8894ae
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 122 deletions.
3 changes: 1 addition & 2 deletions .licenserc.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
{
"**/*.go": "// Copyright 2022 The Project Oak Authors",
"**/BUILD": "# Copyright 2022 The Project Oak Authors"
"**/*.go": ["// Licensed under the Apache License, Version 2.0 (the \"License\");"]
}
6 changes: 3 additions & 3 deletions cmd/verifier/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Verifying provenances

The [`verifier`](/internal/verifier/) package provides functionality for verifying an input SLSA
provenance file. Currently the provenance verifier only parses the provenance files, and verifies
that it contains exactly one subject, containing a SHA256 digest and a binary name.
The [`verification`](/internal/verification/) package provides functionality for verifying an input
SLSA provenance file. Currently the provenance verifier only parses the provenance files, and
verifies that it contains exactly one subject, containing a SHA256 digest and a binary name.

To verify a SLSA v0.2 provenance, run:

Expand Down
10 changes: 5 additions & 5 deletions cmd/verifier/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import (
"log"
"os"

"github.com/project-oak/transparent-release/internal/common"
"github.com/project-oak/transparent-release/internal/verifier"
"github.com/project-oak/transparent-release/internal/model"
"github.com/project-oak/transparent-release/internal/verification"
"github.com/project-oak/transparent-release/pkg/types"
)

Expand All @@ -40,14 +40,14 @@ func main() {
log.Fatalf("couldn't parse bytes from %s into a validated provenance: %v", *provenancePath, err)
}
// Map to internal provenance representation based on the predicate/build type.
provenanceIR, err := common.FromValidatedProvenance(validatedProvenance)
provenanceIR, err := model.FromValidatedProvenance(validatedProvenance)
if err != nil {
log.Fatalf("couldn't map from %s to internal representation: %v", validatedProvenance, err)
}

provenanceVerifier := verifier.ProvenanceIRVerifier{
provenanceVerifier := verification.ProvenanceIRVerifier{
Got: provenanceIR,
Want: &common.ReferenceValues{},
Want: &verification.ReferenceValues{},
}

if err := provenanceVerifier.Verify(); err != nil {
Expand Down
20 changes: 10 additions & 10 deletions internal/endorser/endorser.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ import (

"go.uber.org/multierr"

"github.com/project-oak/transparent-release/internal/common"
"github.com/project-oak/transparent-release/internal/verifier"
"github.com/project-oak/transparent-release/internal/model"
"github.com/project-oak/transparent-release/internal/verification"
"github.com/project-oak/transparent-release/pkg/amber"
"github.com/project-oak/transparent-release/pkg/intoto"
"github.com/project-oak/transparent-release/pkg/types"
Expand All @@ -40,15 +40,15 @@ import (
// wrapped in a DSSE envelope, `SourceMetadata` contains the URI and digest of
// the DSSE document, while `Provenance` contains the provenance itself.
type ParsedProvenance struct {
Provenance common.ProvenanceIR
Provenance model.ProvenanceIR
SourceMetadata amber.ProvenanceData
}

// GenerateEndorsement generates an endorsement statement for the given validity duration, using
// the given provenances as evidence and reference values to verify them. At least one provenance
// must be provided. The endorsement statement is generated only if the provenance statements are
// valid.
func GenerateEndorsement(referenceValues *common.ReferenceValues, validityDuration amber.ClaimValidity, provenances []ParsedProvenance) (*intoto.Statement, error) {
func GenerateEndorsement(referenceValues *verification.ReferenceValues, validityDuration amber.ClaimValidity, provenances []ParsedProvenance) (*intoto.Statement, error) {
verifiedProvenances, err := verifyAndSummarizeProvenances(referenceValues, provenances)
if err != nil {
return nil, fmt.Errorf("could not verify and summarize provenances: %v", err)
Expand All @@ -62,12 +62,12 @@ func GenerateEndorsement(referenceValues *common.ReferenceValues, validityDurati
// (1) The list of provenances is empty,
// (2) Any of the provenances is invalid (see verifyProvenances for details on validity),
// (3) Provenances do not match (e.g., have different binary names).
func verifyAndSummarizeProvenances(referenceValues *common.ReferenceValues, provenances []ParsedProvenance) (*amber.VerifiedProvenanceSet, error) {
func verifyAndSummarizeProvenances(referenceValues *verification.ReferenceValues, provenances []ParsedProvenance) (*amber.VerifiedProvenanceSet, error) {
if len(provenances) == 0 {
return nil, fmt.Errorf("at least one provenance file must be provided")
}

provenanceIRs := make([]common.ProvenanceIR, 0, len(provenances))
provenanceIRs := make([]model.ProvenanceIR, 0, len(provenances))
provenancesData := make([]amber.ProvenanceData, 0, len(provenances))
for _, p := range provenances {
provenanceIRs = append(provenanceIRs, p.Provenance)
Expand All @@ -89,10 +89,10 @@ func verifyAndSummarizeProvenances(referenceValues *common.ReferenceValues, prov
}

// verifyProvenances verifies the given list of provenances. An error is returned if verification fails for one of them.
func verifyProvenances(referenceValues *common.ReferenceValues, provenances []common.ProvenanceIR) error {
func verifyProvenances(referenceValues *verification.ReferenceValues, provenances []model.ProvenanceIR) error {
var errs error
for index := range provenances {
provenanceVerifier := verifier.ProvenanceIRVerifier{
provenanceVerifier := verification.ProvenanceIRVerifier{
Got: &provenances[index],
Want: referenceValues,
}
Expand All @@ -105,7 +105,7 @@ func verifyProvenances(referenceValues *common.ReferenceValues, provenances []co

// verifyConsistency verifies that all provenances have the same binary name and
// binary digest.
func verifyConsistency(provenanceIRs []common.ProvenanceIR) error {
func verifyConsistency(provenanceIRs []model.ProvenanceIR) error {
var errs error

// get the binary digest and binary name of the first provenance as reference
Expand Down Expand Up @@ -160,7 +160,7 @@ func LoadProvenance(provenanceURI string) (*ParsedProvenance, error) {
return nil, fmt.Errorf("couldn't parse bytes from %s into a validated provenance: %v", provenanceURI, err)
}
// Map to internal provenance representation based on the predicate/build type.
provenanceIR, err := common.FromValidatedProvenance(validatedProvenance)
provenanceIR, err := model.FromValidatedProvenance(validatedProvenance)
if err != nil {
return nil, fmt.Errorf("couldn't map from %s to internal representation: %v", validatedProvenance, err)
}
Expand Down
14 changes: 7 additions & 7 deletions internal/endorser/endorser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import (
"testing"
"time"

"github.com/project-oak/transparent-release/internal/common"
"github.com/project-oak/transparent-release/internal/testutil"
"github.com/project-oak/transparent-release/internal/verification"
"github.com/project-oak/transparent-release/pkg/amber"
)

Expand Down Expand Up @@ -50,7 +50,7 @@ func TestGenerateEndorsement_SingleValidEndorsement(t *testing.T) {
t.Fatalf("Could not load provenances: %v", err)
}

referenceValues, err := common.LoadReferenceValuesFromFile("../../testdata/reference_values.toml")
referenceValues, err := verification.LoadReferenceValuesFromFile("../../testdata/reference_values.toml")
if err != nil {
t.Fatalf("Could not load reference values: %v", err)
}
Expand Down Expand Up @@ -83,7 +83,7 @@ func TestLoadAndVerifyProvenances_MultipleValidEndorsement(t *testing.T) {
t.Fatalf("Could not load provenances: %v", err)
}

referenceValues := common.ReferenceValues{
referenceValues := verification.ReferenceValues{
// Make sure we pick the correct binary hash if there are several reference values.
BinarySHA256Digests: []string{binaryHash + "_diff", binaryHash},
}
Expand Down Expand Up @@ -114,7 +114,7 @@ func TestLoadAndVerifyProvenances_ConsistentNotVerified(t *testing.T) {
if err != nil {
t.Fatalf("Could not load provenances: %v", err)
}
referenceValues := common.ReferenceValues{
referenceValues := verification.ReferenceValues{
BinarySHA256Digests: []string{binaryHash + "_diff"},
}

Expand All @@ -140,7 +140,7 @@ func TestLoadAndVerify_InconsistentVerified(t *testing.T) {
if err != nil {
t.Fatalf("Could not load provenances: %v", err)
}
referenceValues := common.ReferenceValues{
referenceValues := verification.ReferenceValues{
BinarySHA256Digests: []string{"e8e05d1d09af8952919bf6ab38e0cc5a6414ee2b5e21f4765b12421c5db0037e", binaryHash},
}

Expand All @@ -167,7 +167,7 @@ func TestLoadAndVerify_InconsistentNotVerified(t *testing.T) {
if err != nil {
t.Fatalf("Could not load provenances: %v", err)
}
referenceValues := common.ReferenceValues{
referenceValues := verification.ReferenceValues{
BinarySHA256Digests: []string{binaryHash + "_diff"},
}

Expand All @@ -192,7 +192,7 @@ func TestLoadAndVerifyProvenances_NotVerified(t *testing.T) {
if err != nil {
t.Fatalf("Could not load provenances: %v", err)
}
referenceValues, err := common.LoadReferenceValuesFromFile("../../testdata/different_reference_values.toml")
referenceValues, err := verification.LoadReferenceValuesFromFile("../../testdata/different_reference_values.toml")
if err != nil {
t.Fatalf("Could not load reference values: %v", err)
}
Expand Down
36 changes: 4 additions & 32 deletions internal/common/common.go → internal/model/provenance.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// Package common provides utility functions for building and verifying released binaries.
package common
// Package model provides the internal representation of a provenance statement
// and utilities for parsing different types of provenances into this internal
// representation
package model

import (
"crypto/sha256"
"encoding/hex"
"fmt"
"os"

toml "github.com/pelletier/go-toml"
slsav02 "github.com/project-oak/transparent-release/pkg/intoto/slsa_provenance/v0.2"

"github.com/project-oak/transparent-release/pkg/intoto"
"github.com/project-oak/transparent-release/pkg/types"
)

// ReferenceValues given by the product team to verify provenances against.
type ReferenceValues struct {
// The digests of the binaries whose provenance the product team wants to verify.
BinarySHA256Digests []string `toml:"binary_sha256_digests"`
// If true the product team wants the provenance to have a non-empty build command.
WantBuildCmds bool `toml:"want_build_cmds"`
// The digests of the builder images the product team trusts to build the binary.
BuilderImageSHA256Digests []string `toml:"builder_image_sha256_digests"`
// The URI of the repo holding the resources the binary is built from.
RepoURI string `toml:"repo_uri"`
// The builders a product team trusts to build the binary.
TrustedBuilders []string `toml:"trusted_builders"`
}

// ProvenanceIR is an internal intermediate representation of data from provenances.
// We want to map different provenances of different build types to ProvenanceIR, so
// all fields except for `binarySHA256Digest`, `buildType`, and `binaryName` are optional.
Expand Down Expand Up @@ -213,21 +200,6 @@ func fromSLSAv02(provenance *types.ValidatedProvenance) (*ProvenanceIR, error) {
return provenanceIR, nil
}

// LoadReferenceValuesFromFile loads reference values from a toml file in the given path and returns an instance of ReferenceValues.
func LoadReferenceValuesFromFile(path string) (*ReferenceValues, error) {
tomlTree, err := toml.LoadFile(path)
if err != nil {
return nil, fmt.Errorf("couldn't load toml file: %v", err)
}

referenceValues := ReferenceValues{}
if err := tomlTree.Unmarshal(&referenceValues); err != nil {
return nil, fmt.Errorf("couldn't unmarshal toml file: %v", err)
}

return &referenceValues, nil
}

// ComputeSHA256Digest returns the SHA256 digest of the file in the given path, or an error if the
// file cannot be read.
func ComputeSHA256Digest(path string) (string, error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package common
package model

import (
"fmt"
Expand All @@ -21,7 +21,6 @@ import (
"testing"

"github.com/google/go-cmp/cmp"
"github.com/project-oak/transparent-release/internal/testutil"
slsav02 "github.com/project-oak/transparent-release/pkg/intoto/slsa_provenance/v0.2"
"github.com/project-oak/transparent-release/pkg/types"
)
Expand All @@ -44,18 +43,6 @@ func TestComputeBinarySHA256Digest(t *testing.T) {
}
}

func TestParseReferenceValues(t *testing.T) {
path := filepath.Join(testdataPath, "reference_values.toml")
referenceValues, err := LoadReferenceValuesFromFile(path)
if err != nil {
t.Fatalf("couldn't load reference values file: %v", err)
}

testutil.AssertEq(t, "binary digests[0]", referenceValues.BinarySHA256Digests[0], "d059c38cea82047ad316a1c6c6fbd13ecf7a0abdcc375463920bd25bf5c142cc")
testutil.AssertEq(t, "want build cmd", referenceValues.WantBuildCmds, false)
testutil.AssertEq(t, "builder image digests[0]", referenceValues.BuilderImageSHA256Digests[0], "9e2ba52487d945504d250de186cb4fe2e3ba023ed2921dd6ac8b97ed43e76af9")
}

func TestFromProvenance_Slsav02(t *testing.T) {
path := filepath.Join(testdataPath, slsav02ProvenancePath)
statementBytes, err := os.ReadFile(path)
Expand Down
50 changes: 50 additions & 0 deletions internal/verification/reference.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2023 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package verification

import (
"fmt"

"github.com/pelletier/go-toml"
)

// ReferenceValues specify expected values to verify provenances against.
type ReferenceValues struct {
// Allow list of binary digests.
BinarySHA256Digests []string `toml:"binary_sha256_digests"`
// If true, expect that the provenance has a non-empty build command.
WantBuildCmds bool `toml:"want_build_cmds"`
// Allow list of builder image digests that are trusted for building the binary.
BuilderImageSHA256Digests []string `toml:"builder_image_sha256_digests"`
// The URI of the repo holding the resources the binary is built from.
RepoURI string `toml:"repo_uri"`
// Allow list of builders trusted to build the binary.
TrustedBuilders []string `toml:"trusted_builders"`
}

// LoadReferenceValuesFromFile loads reference values from a toml file in the given path and returns an instance of ReferenceValues.
func LoadReferenceValuesFromFile(path string) (*ReferenceValues, error) {
tomlTree, err := toml.LoadFile(path)
if err != nil {
return nil, fmt.Errorf("couldn't load toml file: %v", err)
}

referenceValues := ReferenceValues{}
if err := tomlTree.Unmarshal(&referenceValues); err != nil {
return nil, fmt.Errorf("couldn't unmarshal toml file: %v", err)
}

return &referenceValues, nil
}
38 changes: 38 additions & 0 deletions internal/verification/reference_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2023 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package verification

import (
"path/filepath"
"testing"

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

const (
testdataPath = "../../testdata/"
)

func TestParseReferenceValues(t *testing.T) {
path := filepath.Join(testdataPath, "reference_values.toml")
referenceValues, err := LoadReferenceValuesFromFile(path)
if err != nil {
t.Fatalf("couldn't load reference values file: %v", err)
}

testutil.AssertEq(t, "binary digests[0]", referenceValues.BinarySHA256Digests[0], "d059c38cea82047ad316a1c6c6fbd13ecf7a0abdcc375463920bd25bf5c142cc")
testutil.AssertEq(t, "want build cmd", referenceValues.WantBuildCmds, false)
testutil.AssertEq(t, "builder image digests[0]", referenceValues.BuilderImageSHA256Digests[0], "9e2ba52487d945504d250de186cb4fe2e3ba023ed2921dd6ac8b97ed43e76af9")
}
Loading

0 comments on commit d8894ae

Please sign in to comment.