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

Refactor package common #226

Merged
merged 5 commits into from
Apr 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why these are only sha256? Could they not be arbitrary digests, as long as they have the appropriate prefix?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general they could, but we use SHA256. We can relax this restriction in the future if needed.

// 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"`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For slice fields, I assume that means that any of those values is sufficient?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Updated the comment to better reflect this.

// 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