Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix intoto statement marshal/unmarshal #326

Closed
Closed
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
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ require (
github.com/go-openapi/swag v0.23.0
github.com/google/certificate-transparency-go v1.2.1
github.com/in-toto/attestation v1.1.0
github.com/in-toto/in-toto-golang v0.9.0
github.com/secure-systems-lab/go-securesystemslib v0.8.0
github.com/sigstore/protobuf-specs v0.3.2
github.com/sigstore/rekor v1.3.6
Expand Down Expand Up @@ -51,6 +50,7 @@ require (
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/in-toto/in-toto-golang v0.9.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jedisct1/go-minisign v0.0.0-20211028175153-1c139d1cc84b // indirect
github.com/josharian/intern v1.0.0 // indirect
Expand Down
5 changes: 2 additions & 3 deletions pkg/bundle/signature_content.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package bundle
import (
"encoding/base64"

in_toto "github.com/in-toto/attestation/go/v1"
"github.com/secure-systems-lab/go-securesystemslib/dsse"
"github.com/sigstore/sigstore-go/pkg/verify"
"google.golang.org/protobuf/encoding/protojson"
Expand Down Expand Up @@ -51,12 +50,12 @@ type Envelope struct {
*dsse.Envelope
}

func (e *Envelope) Statement() (*in_toto.Statement, error) {
func (e *Envelope) Statement() (*verify.Statement, error) {
if e.PayloadType != IntotoMediaType {
return nil, ErrUnsupportedMediaType
}

var statement in_toto.Statement
var statement verify.Statement
raw, err := e.DecodeB64Payload()
if err != nil {
return nil, ErrDecodingB64
Expand Down
3 changes: 1 addition & 2 deletions pkg/verify/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"errors"
"time"

in_toto "github.com/in-toto/attestation/go/v1"
"github.com/secure-systems-lab/go-securesystemslib/dsse"
protocommon "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1"
"github.com/sigstore/sigstore-go/pkg/root"
Expand Down Expand Up @@ -86,7 +85,7 @@ type MessageSignatureContent interface {

type EnvelopeContent interface {
RawEnvelope() *dsse.Envelope
Statement() (*in_toto.Statement, error)
Statement() (*Statement, error)
}

// BaseSignedEntity is a helper struct that implements all the interfaces
Expand Down
18 changes: 8 additions & 10 deletions pkg/verify/signature_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ import (
"fmt"
"testing"

"github.com/in-toto/in-toto-golang/in_toto"
"github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common"
in_toto "github.com/in-toto/attestation/go/v1"
"github.com/sigstore/sigstore-go/pkg/testing/ca"
"github.com/sigstore/sigstore-go/pkg/verify"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -121,17 +120,17 @@ func TestTooManySubjects(t *testing.T) {
virtualSigstore, err := ca.NewVirtualSigstore()
assert.NoError(t, err)

tooManySubjectsStatement := in_toto.Statement{}
tooManySubjectsStatement := verify.Statement{}
for i := 0; i < 1025; i++ {
tooManySubjectsStatement.Subject = append(tooManySubjectsStatement.Subject, in_toto.Subject{
tooManySubjectsStatement.Subject = append(tooManySubjectsStatement.Subject, &in_toto.ResourceDescriptor{
Name: fmt.Sprintf("subject-%d", i),
Digest: map[string]string{
"sha256": "", // actual content of digest does not matter for this test
},
})
}

tooManySubjectsStatementBytes, err := json.Marshal(tooManySubjectsStatement)
tooManySubjectsStatementBytes, err := json.Marshal(&tooManySubjectsStatement)
assert.NoError(t, err)

tooManySubjectsEntity, err := virtualSigstore.Attest("foo@example.com", "issuer", tooManySubjectsStatementBytes)
Expand All @@ -149,19 +148,18 @@ func TestTooManyDigests(t *testing.T) {
virtualSigstore, err := ca.NewVirtualSigstore()
assert.NoError(t, err)

tooManyDigestsStatement := in_toto.Statement{}
tooManyDigestsStatement.Subject = []in_toto.Subject{
tooManyDigestsStatement := verify.Statement{}
tooManyDigestsStatement.Subject = []*in_toto.ResourceDescriptor{
{
Name: fmt.Sprintf("subject"),
Digest: make(common.DigestSet),
Digest: map[string]string{"sha512": ""},
},
}
tooManyDigestsStatement.Subject[0].Digest["sha512"] = "" // verifier requires that at least one known hash algorithm is present in the digest map
for i := 0; i < 32; i++ {
tooManyDigestsStatement.Subject[0].Digest[fmt.Sprintf("digest-%d", i)] = ""
}

tooManySubjectsStatementBytes, err := json.Marshal(tooManyDigestsStatement)
tooManySubjectsStatementBytes, err := json.Marshal(&tooManyDigestsStatement)
assert.NoError(t, err)

tooManySubjectsEntity, err := virtualSigstore.Attest("foo@example.com", "issuer", tooManySubjectsStatementBytes)
Expand Down
15 changes: 14 additions & 1 deletion pkg/verify/signed_entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/sigstore/sigstore-go/pkg/fulcio/certificate"
"github.com/sigstore/sigstore-go/pkg/root"
"github.com/sigstore/sigstore/pkg/cryptoutils"
"google.golang.org/protobuf/encoding/protojson"
)

const (
Expand Down Expand Up @@ -216,7 +217,7 @@ func (c *VerifierConfig) Validate() error {

type VerificationResult struct {
MediaType string `json:"mediaType"`
Statement *in_toto.Statement `json:"statement,omitempty"`
Statement *Statement `json:"statement,omitempty"`
Signature *SignatureVerificationResult `json:"signature,omitempty"`
VerifiedTimestamps []TimestampVerificationResult `json:"verifiedTimestamps"`
VerifiedIdentity *CertificateIdentity `json:"verifiedIdentity,omitempty"`
Expand All @@ -239,6 +240,18 @@ func NewVerificationResult() *VerificationResult {
}
}

type Statement struct {
in_toto.Statement
}

func (s *Statement) MarshalJSON() ([]byte, error) {
return protojson.Marshal(&s.Statement)
}

func (s *Statement) UnmarshalJSON(data []byte) error {
return protojson.Unmarshal(data, s)
}

type PolicyOption func(*PolicyConfig) error
type ArtifactPolicyOption func(*PolicyConfig) error

Expand Down
39 changes: 39 additions & 0 deletions pkg/verify/signed_entity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ import (
"encoding/hex"
"encoding/json"

in_toto "github.com/in-toto/attestation/go/v1"
"github.com/sigstore/sigstore-go/pkg/testing/data"
"github.com/sigstore/sigstore-go/pkg/verify"
"github.com/stretchr/testify/assert"
"google.golang.org/protobuf/types/known/structpb"
)

func TestSignedEntityVerifierInitialization(t *testing.T) {
Expand Down Expand Up @@ -422,3 +424,40 @@ func TestSigstoreBundle2Sig(t *testing.T) {
assert.True(t, errors.Is(err, verify.ErrDSSEInvalidSignatureCount))
assert.Nil(t, res)
}

func TestStatementSerializesToValidInTotoStatement(t *testing.T) {
// create instance of verify.Statement with dummy values
statement := verify.Statement{}
statement.Type = "https://in-toto.io/Statement/v0.1"
statement.PredicateType = "https://example.org/predicate"
statement.Subject = []*in_toto.ResourceDescriptor{
{
Name: "artifact-name",
Digest: map[string]string{
"sha256": "artifact-digest",
},
},
}
statement.Predicate = &structpb.Struct{
Fields: map[string]*structpb.Value{},
}

// marshal the statement to JSON
statementJSON, err := json.Marshal(&statement)
assert.NoError(t, err)
want := `
{
"_type": "https://in-toto.io/Statement/v0.1",
"predicateType": "https://example.org/predicate",
"subject": [
{
"name": "artifact-name",
"digest": {
"sha256": "artifact-digest"
}
}
],
"predicate": {}
}`
assert.JSONEq(t, want, string(statementJSON))
}