Skip to content

Commit

Permalink
name stored attestations by digest instead of UUID (#769)
Browse files Browse the repository at this point in the history
* store attestations by digest instead of by UUID

Signed-off-by: Bob Callaway <bcallaway@google.com>

* fix typo

Signed-off-by: Bob Callaway <bcallaway@google.com>

* remove github.com/pkg/errors

Signed-off-by: Bob Callaway <bcallaway@google.com>
  • Loading branch information
bobcallaway authored May 24, 2022
1 parent f61a71e commit e375eb4
Show file tree
Hide file tree
Showing 13 changed files with 114 additions and 44 deletions.
46 changes: 36 additions & 10 deletions pkg/api/entries.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"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"
Expand Down Expand Up @@ -97,12 +98,35 @@ 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
activeTree := fmt.Sprintf("%x", tc.logID)
entryIDstruct, err := sharding.CreateEntryIDFromParts(activeTree, uuid)
if err != nil {
err := fmt.Errorf("error creating EntryID from active treeID %v and uuid %v: %w", activeTree, uuid, err)
return nil, err
}
att, err = storageClient.FetchAttestation(ctx, entryIDstruct.UUID)
if err != nil {
log.Logger.Errorf("error fetching attestation by uuid: %s %s", entryIDstruct.UUID, err)
}
}
if err == nil {
logEntryAnon.Attestation = &models.LogEntryAnonAttestation{
Data: att,
}
}
}
}
Expand Down Expand Up @@ -224,14 +248,16 @@ func createLogEntry(params entries.CreateLogEntryParams) (models.LogEntry, middl
if viper.GetBool("enable_attestation_storage") {

go func() {
attestation := entry.Attestation()
if attestation == nil {
log.RequestIDLogger(params.HTTPRequest).Infof("no attestation for %s", entryID)
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(), entryIDstruct.UUID, attestation); err != nil {
if err := storeAttestation(context.Background(), attKey, attVal); err != nil {
// entryIDstruct.UUID
log.RequestIDLogger(params.HTTPRequest).Errorf("error storing attestation: %s", err)
} else {
log.RequestIDLogger(params.HTTPRequest).Infof("stored attestation for uuid %s with filename %s", entryIDstruct.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 @@ -287,8 +287,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 @@ -280,8 +280,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 @@ -182,16 +182,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, fmt.Errorf("decoding attestation: %w", err)
}
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 @@ -237,13 +232,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 @@ -271,8 +271,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 @@ -332,8 +332,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 @@ -307,8 +307,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 @@ -294,8 +294,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 @@ -196,7 +196,7 @@ func TestLogInfo(t *testing.T) {
}

type getOut struct {
Attestation []byte
Attestation string
AttestationType string
Body interface{}
LogIndex int
Expand Down Expand Up @@ -447,17 +447,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

0 comments on commit e375eb4

Please sign in to comment.