Skip to content

Commit

Permalink
Verify text provenance for GCB (#242)
Browse files Browse the repository at this point in the history
* update

* update

* update

* update

* update

* comments

* comments
  • Loading branch information
laurentsimon committed Aug 30, 2022
1 parent 71cf039 commit 26c928f
Show file tree
Hide file tree
Showing 6 changed files with 731 additions and 2 deletions.
1 change: 1 addition & 0 deletions errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ var (
ErrorInvalidSemver = errors.New("invalid semantic version")
ErrorRekorSearch = errors.New("error searching rekor entries")
ErrorMismatchHash = errors.New("artifact hash does not match provenance subject")
ErrorMismatchIntoto = errors.New("verified intoto provenance does not match text provenance")
ErrorInvalidRef = errors.New("invalid ref")
ErrorUntrustedReusableWorkflow = errors.New("untrusted reusable workflow")
ErrorNoValidRekorEntries = errors.New("could not find a matching valid signature entry")
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ require (
github.com/go-openapi/swag v0.22.3
github.com/google/go-containerregistry v0.11.0
github.com/gorilla/mux v1.8.0
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/sigstore/cosign v1.11.0
github.com/slsa-framework/slsa-github-generator v1.2.0
github.com/transparency-dev/merkle v0.0.1
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1414,6 +1414,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k=
Expand Down
41 changes: 39 additions & 2 deletions verifiers/internal/gcb/provenance.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import (
"encoding/json"
"fmt"
"os"
"reflect"
"regexp"
"strings"

"github.com/google/go-cmp/cmp"

intoto "github.com/in-toto/in-toto-golang/in_toto"
slsa01 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.1"
dsselib "github.com/secure-systems-lab/go-securesystemslib/dsse"
Expand All @@ -25,10 +28,18 @@ type v01IntotoStatement struct {
Predicate slsa01.ProvenancePredicate `json:"predicate"`
}

// The GCB provenance contains a human-readable version of the intoto
// statement, but it is not compliant with the standard. It uses `slsaProvenance`
// instead of `predicate`. For backward compatibility, this has not been fixed
// by the GCB team.
type v01GCBIntotoStatement struct {
intoto.StatementHeader
SlsaProvenance slsa01.ProvenancePredicate `json:"slsaProvenance"`
}

type provenance struct {
Build struct {
// TODO: compare to verified provenance.
// IntotoStatement v01IntotoStatement `json:"intotoStatement"`
UnverifiedTextIntotoStatement v01GCBIntotoStatement `json:"intotoStatement"`
} `json:"build"`
Kind string `json:"kind"`
ResourceURI string `json:"resourceUri"`
Expand Down Expand Up @@ -149,6 +160,32 @@ func (self *Provenance) VerifySummary(provenanceOpts *options.ProvenanceOpts) er
return nil
}

// VerifyTextProvenance verifies the text provenance prepended
// to the provenance.This text mirrors the DSSE payload but is human-readable.
func (self *Provenance) VerifyTextProvenance() error {
if err := self.isVerified(); err != nil {
return err
}

// Note: there is an additional field `metadata.buildInvocationId` which
// is not part of the specs but is present. This field is currently ignored during comparison.
unverifiedTextIntotoStatement := v01IntotoStatement{
StatementHeader: self.verifiedProvenance.Build.UnverifiedTextIntotoStatement.StatementHeader,
Predicate: self.verifiedProvenance.Build.UnverifiedTextIntotoStatement.SlsaProvenance,
}

// Note: DeepEqual() has problem with time comparisons: https://github.com/onsi/gomega/issues/264
// but this should not affect us since both times are supposed to have the the same string and
// they are both taken from a strng representation.
// We do not use cmp.Equal() because it *can* panic and is intended for unit tests only.
if !reflect.DeepEqual(unverifiedTextIntotoStatement, *self.verifiedIntotoStatement) {
return fmt.Errorf("%w: diff '%s'", serrors.ErrorMismatchIntoto,
cmp.Diff(unverifiedTextIntotoStatement, *self.verifiedIntotoStatement))
}

return nil
}

// VerifyIntotoHeaders verifies the headers are intoto format and the expected
// slsa predicate.
func (self *Provenance) VerifyIntotoHeaders() error {
Expand Down
Loading

0 comments on commit 26c928f

Please sign in to comment.