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

name stored attestations by digest instead of UUID #769

Merged
merged 5 commits into from
May 24, 2022
Merged
Show file tree
Hide file tree
Changes from 2 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
39 changes: 29 additions & 10 deletions pkg/api/entries.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,20 @@ import (
"bytes"
"context"
"encoding/hex"
"errors"
"fmt"
"net/http"
"net/url"
"strconv"

"github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer"
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/google/trillian"
"github.com/google/trillian/merkle/rfc6962"
ttypes "github.com/google/trillian/types"
"github.com/pkg/errors"
"github.com/spf13/viper"
"golang.org/x/sync/errgroup"
"google.golang.org/genproto/googleapis/rpc/code"
Expand Down Expand Up @@ -97,12 +98,29 @@ func logEntryFromLeaf(ctx context.Context, signer signature.Signer, tc TrillianC

uuid := hex.EncodeToString(leaf.MerkleLeafHash)
if viper.GetBool("enable_attestation_storage") {
att, err := storageClient.FetchAttestation(ctx, uuid)
pe, err := models.UnmarshalProposedEntry(bytes.NewReader(leaf.LeafValue), runtime.JSONConsumer())
if err != nil {
log.Logger.Errorf("error fetching attestation: %s %s", uuid, err)
} else {
logEntryAnon.Attestation = &models.LogEntryAnonAttestation{
Data: att,
return nil, err
}
eimpl, err := types.NewEntry(pe)
if err != nil {
return nil, err
}
attKey := eimpl.AttestationKey()
if attKey != "" {
att, err := storageClient.FetchAttestation(ctx, attKey)
if err != nil {
log.Logger.Errorf("error fetching attestation by key, trying by UUID: %s %s", attKey, err)
// the original attestation implementation stored this by uuid instead of by digest
att, err = storageClient.FetchAttestation(ctx, uuid)
if err != nil {
log.Logger.Errorf("error fetching attestation by uuid: %s %s", uuid, err)
}
}
if err == nil {
logEntryAnon.Attestation = &models.LogEntryAnonAttestation{
Data: att,
}
}
}
}
Expand Down Expand Up @@ -216,14 +234,15 @@ func createLogEntry(params entries.CreateLogEntryParams) (models.LogEntry, middl
if viper.GetBool("enable_attestation_storage") {

go func() {
attestation := entry.Attestation()
if attestation == nil {
attKey, attVal := entry.AttestationKeyValue()
if attVal == nil {
log.RequestIDLogger(params.HTTPRequest).Infof("no attestation for %s", uuid)
return
}
// TODO stop using uuid and use attestation hash
if err := storeAttestation(context.Background(), uuid, attestation); err != nil {
if err := storeAttestation(context.Background(), attKey, attVal); err != nil {
log.RequestIDLogger(params.HTTPRequest).Errorf("error storing attestation: %s", err)
} else {
log.RequestIDLogger(params.HTTPRequest).Infof("stored attestation for uuid %s with filename %s", uuid, attKey)
}
}()
}
Expand Down
8 changes: 6 additions & 2 deletions pkg/types/alpine/v0.0.1/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,12 @@ func (v V001Entry) validate() error {
return nil
}

func (v V001Entry) Attestation() []byte {
return nil
func (v V001Entry) AttestationKey() string {
return ""
}

func (v V001Entry) AttestationKeyValue() (string, []byte) {
return "", nil
}

func (v V001Entry) CreateFromArtifactProperties(ctx context.Context, props types.ArtifactProperties) (models.ProposedEntry, error) {
Expand Down
3 changes: 2 additions & 1 deletion pkg/types/entries.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ type EntryImpl interface {
IndexKeys() ([]string, error) // the keys that should be added to the external index for this entry
Canonicalize(ctx context.Context) ([]byte, error) // marshal the canonical entry to be put into the tlog
Unmarshal(e models.ProposedEntry) error // unmarshal the abstract entry into the specific struct for this versioned type
Attestation() []byte
AttestationKey() string // returns the key used to look up the attestation from storage (should be sha256:digest)
AttestationKeyValue() (string, []byte) // returns the key to be used when storing the attestation as well as the attestation itself
CreateFromArtifactProperties(context.Context, ArtifactProperties) (models.ProposedEntry, error)
}

Expand Down
8 changes: 6 additions & 2 deletions pkg/types/hashedrekord/v0.0.1/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,12 @@ func (v *V001Entry) validate() (pki.Signature, pki.PublicKey, error) {
return sigObj, keyObj, nil
}

func (v V001Entry) Attestation() []byte {
return nil
func (v V001Entry) AttestationKey() string {
return ""
}

func (v V001Entry) AttestationKeyValue() (string, []byte) {
return "", nil
}

func (v V001Entry) CreateFromArtifactProperties(ctx context.Context, props types.ArtifactProperties) (models.ProposedEntry, error) {
Expand Down
8 changes: 6 additions & 2 deletions pkg/types/helm/v0.0.1/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,12 @@ func (v V001Entry) validate() error {
return nil
}

func (v V001Entry) Attestation() []byte {
return nil
func (v V001Entry) AttestationKey() string {
return ""
}

func (v V001Entry) AttestationKeyValue() (string, []byte) {
return "", nil
}

func (v V001Entry) CreateFromArtifactProperties(ctx context.Context, props types.ArtifactProperties) (models.ProposedEntry, error) {
Expand Down
29 changes: 18 additions & 11 deletions pkg/types/intoto/v0.0.1/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,11 @@ func (v *V001Entry) Canonicalize(ctx context.Context) ([]byte, error) {
},
},
}
attestation := v.Attestation()
if attestation != nil {
decodedAttestation, err := base64.StdEncoding.DecodeString(string(attestation))
if err != nil {
return nil, errors.Wrap(err, "decoding attestation")
}
attH := sha256.Sum256(decodedAttestation)
attKey, attValue := v.AttestationKeyValue()
if attValue != nil {
canonicalEntry.Content.PayloadHash = &models.IntotoV001SchemaContentPayloadHash{
Algorithm: swag.String(models.IntotoV001SchemaContentHashAlgorithmSha256),
Value: swag.String(hex.EncodeToString(attH[:])),
Value: swag.String(strings.Replace(attKey, fmt.Sprintf("%s:", models.IntotoV001SchemaContentHashAlgorithmSha256), "", 1)),
}
}

Expand Down Expand Up @@ -210,13 +205,25 @@ func (v *V001Entry) validate() error {
return nil
}

func (v *V001Entry) Attestation() []byte {
// AttestationKey returns the digest of the attestation that was uploaded, to be used to lookup the attestation from storage
func (v *V001Entry) AttestationKey() string {
if v.IntotoObj.Content != nil && v.IntotoObj.Content.PayloadHash != nil {
return fmt.Sprintf("%s:%s", *v.IntotoObj.Content.PayloadHash.Algorithm, *v.IntotoObj.Content.PayloadHash.Value)
}
return ""
}

// AttestationKeyValue returns both the key and value to be persisted into attestation storage
func (v *V001Entry) AttestationKeyValue() (string, []byte) {
storageSize := base64.StdEncoding.DecodedLen(len(v.env.Payload))
if storageSize > viper.GetInt("max_attestation_size") {
log.Logger.Infof("Skipping attestation storage, size %d is greater than max %d", storageSize, viper.GetInt("max_attestation_size"))
return nil
return "", nil
}
return []byte(v.env.Payload)
attBytes, _ := base64.StdEncoding.DecodeString(v.env.Payload)
attHash := sha256.Sum256(attBytes)
attKey := fmt.Sprintf("%s:%s", models.IntotoV001SchemaContentHashAlgorithmSha256, hex.EncodeToString(attHash[:]))
return attKey, attBytes
}

type verifier struct {
Expand Down
8 changes: 6 additions & 2 deletions pkg/types/jar/v0.0.1/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,12 @@ func extractPKCS7SignatureFromJAR(inz *zip.Reader) ([]byte, error) {
return nil, errors.New("unable to locate signature in JAR file")
}

func (v *V001Entry) Attestation() []byte {
return nil
func (v V001Entry) AttestationKey() string {
return ""
}

func (v V001Entry) AttestationKeyValue() (string, []byte) {
return "", nil
}

func (v *V001Entry) CreateFromArtifactProperties(ctx context.Context, props types.ArtifactProperties) (models.ProposedEntry, error) {
Expand Down
8 changes: 6 additions & 2 deletions pkg/types/rekord/v0.0.1/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,8 +355,12 @@ func (v V001Entry) validate() error {
return nil
}

func (v V001Entry) Attestation() []byte {
return nil
func (v V001Entry) AttestationKey() string {
return ""
}

func (v V001Entry) AttestationKeyValue() (string, []byte) {
return "", nil
}

func (v V001Entry) CreateFromArtifactProperties(ctx context.Context, props types.ArtifactProperties) (models.ProposedEntry, error) {
Expand Down
8 changes: 6 additions & 2 deletions pkg/types/rfc3161/v0.0.1/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,12 @@ func (v V001Entry) validate() error {
return nil
}

func (v V001Entry) Attestation() []byte {
return nil
func (v V001Entry) AttestationKey() string {
return ""
}

func (v V001Entry) AttestationKeyValue() (string, []byte) {
return "", nil
}

func (v V001Entry) CreateFromArtifactProperties(_ context.Context, props types.ArtifactProperties) (models.ProposedEntry, error) {
Expand Down
8 changes: 6 additions & 2 deletions pkg/types/rpm/v0.0.1/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,8 +323,12 @@ func (v V001Entry) validate() error {
return nil
}

func (v V001Entry) Attestation() []byte {
return nil
func (v V001Entry) AttestationKey() string {
return ""
}

func (v V001Entry) AttestationKeyValue() (string, []byte) {
return "", nil
}

func (v V001Entry) CreateFromArtifactProperties(ctx context.Context, props types.ArtifactProperties) (models.ProposedEntry, error) {
Expand Down
8 changes: 6 additions & 2 deletions pkg/types/test_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,12 @@ func (u BaseUnmarshalTester) Validate() error {
return nil
}

func (u BaseUnmarshalTester) Attestation() []byte {
return nil
func (u BaseUnmarshalTester) AttestationKey() string {
return ""
}

func (u BaseUnmarshalTester) AttestationKeyValue() (string, []byte) {
return "", nil
}

func (u BaseUnmarshalTester) CreateFromArtifactProperties(_ context.Context, _ ArtifactProperties) (models.ProposedEntry, error) {
Expand Down
8 changes: 6 additions & 2 deletions pkg/types/tuf/v0.0.1/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,8 +315,12 @@ func (v V001Entry) Validate() error {
return nil
}

func (v *V001Entry) Attestation() []byte {
return nil
func (v V001Entry) AttestationKey() string {
return ""
}

func (v V001Entry) AttestationKeyValue() (string, []byte) {
return "", nil
}

func (v V001Entry) CreateFromArtifactProperties(ctx context.Context, props types.ArtifactProperties) (models.ProposedEntry, error) {
Expand Down
8 changes: 4 additions & 4 deletions tests/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ func TestLogInfo(t *testing.T) {
}

type getOut struct {
Attestation []byte
Attestation string
AttestationType string
Body interface{}
LogIndex int
Expand Down Expand Up @@ -450,17 +450,17 @@ func TestIntoto(t *testing.T) {
if err := json.Unmarshal([]byte(out), &g); err != nil {
t.Fatal(err)
}
// The attestation should be stored at /var/run/attestations/$uuid
// The attestation should be stored at /var/run/attestations/sha256:digest

got := in_toto.ProvenanceStatement{}
if err := json.Unmarshal(g.Attestation, &got); err != nil {
if err := json.Unmarshal([]byte(g.Attestation), &got); err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(it, got); diff != "" {
t.Errorf("diff: %s", diff)
}

attHash := sha256.Sum256(g.Attestation)
attHash := sha256.Sum256(b)

intotoModel := &models.IntotoV001Schema{}
if err := types.DecodeEntry(g.Body.(map[string]interface{})["IntotoObj"], intotoModel); err != nil {
Expand Down