Skip to content

Commit

Permalink
(f) DRY: loadPayload across MB.Load, loadEnvelope, LoadMetadata
Browse files Browse the repository at this point in the history
Signed-off-by: Aditya Sirish <aditya@saky.in>
  • Loading branch information
adityasaky committed May 3, 2023
1 parent cd9d2ff commit 4cbd94d
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 131 deletions.
54 changes: 9 additions & 45 deletions in_toto/envelope.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import (
"errors"
"fmt"
"os"
"reflect"
"strings"

"github.com/secure-systems-lab/go-securesystemslib/cjson"
"github.com/secure-systems-lab/go-securesystemslib/dsse"
Expand All @@ -28,10 +26,18 @@ type Envelope struct {

func loadEnvelope(env *dsse.Envelope) (*Envelope, error) {
e := &Envelope{envelope: env}
if err := e.loadPayload(); err != nil {

contentBytes, err := env.DecodeB64Payload()
if err != nil {
return nil, err
}

payload, err := loadPayload(contentBytes)
if err != nil {
return nil, err
}
e.payload = payload

return e, nil
}

Expand All @@ -54,48 +60,6 @@ func (e *Envelope) GetPayload() any {
return e.payload
}

func (e *Envelope) loadPayload() error {
payloadBytes, err := e.envelope.DecodeB64Payload()
if err != nil {
return fmt.Errorf("error decoding payload: %w", err)
}

var payload map[string]any
if err := json.Unmarshal(payloadBytes, &payload); err != nil {
return fmt.Errorf("error decoding payload: %w", err)
}

if payload["_type"] == "link" {
var link Link
if err := checkRequiredJSONFields(payload, reflect.TypeOf(link)); err != nil {
return fmt.Errorf("error decoding payload: %w", err)
}

decoder := json.NewDecoder(strings.NewReader(string(payloadBytes)))
decoder.DisallowUnknownFields()
if err := decoder.Decode(&link); err != nil {
return fmt.Errorf("error decoding payload: %w", err)
}

e.payload = link
} else if payload["_type"] == "layout" {
var layout Layout
if err := checkRequiredJSONFields(payload, reflect.TypeOf(layout)); err != nil {
return fmt.Errorf("error decoding payload: %w", err)
}

decoder := json.NewDecoder(strings.NewReader(string(payloadBytes)))
decoder.DisallowUnknownFields()
if err := decoder.Decode(&layout); err != nil {
return fmt.Errorf("error decoding payload: %w", err)
}

e.payload = layout
}

return nil
}

func (e *Envelope) VerifySignature(key Key) error {
verifier, err := getSignerVerifierFromKey(key)
if err != nil {
Expand Down
90 changes: 6 additions & 84 deletions in_toto/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -728,50 +728,12 @@ func LoadMetadata(path string) (Metadata, error) {
return nil, err
}

// Temporarily copy signed to opaque map to inspect the `_type` of signed
// and create link or layout accordingly
var signed map[string]interface{}
if err := json.Unmarshal(*rawData["signed"], &signed); err != nil {
payload, err := loadPayload(*rawData["signed"])
if err != nil {
return nil, err
}

if signed["_type"] == "link" {
var link Link
if err := checkRequiredJSONFields(signed, reflect.TypeOf(link)); err != nil {
return nil, err
}

data, err := rawData["signed"].MarshalJSON()
if err != nil {
return nil, err
}
decoder := json.NewDecoder(strings.NewReader(string(data)))
decoder.DisallowUnknownFields()
if err := decoder.Decode(&link); err != nil {
return nil, err
}
mb.Signed = link

} else if signed["_type"] == "layout" {
var layout Layout
if err := checkRequiredJSONFields(signed, reflect.TypeOf(layout)); err != nil {
return nil, err
}

data, err := rawData["signed"].MarshalJSON()
if err != nil {
return nil, err
}
decoder := json.NewDecoder(strings.NewReader(string(data)))
decoder.DisallowUnknownFields()
if err := decoder.Decode(&layout); err != nil {
return nil, err
}

mb.Signed = layout
} else {
return nil, fmt.Errorf("the '_type' field of the 'signed' part of in-toto metadata must be one of 'link' or 'layout'")
}
mb.Signed = payload

return mb, nil
}
Expand Down Expand Up @@ -873,52 +835,12 @@ func (mb *Metablock) Load(path string) error {
return err
}

// Temporarily copy signed to opaque map to inspect the `_type` of signed
// and create link or layout accordingly
var signed map[string]interface{}
if err := json.Unmarshal(*rawMb["signed"], &signed); err != nil {
payload, err := loadPayload(*rawMb["signed"])
if err != nil {
return err
}

if signed["_type"] == "link" {
var link Link
if err := checkRequiredJSONFields(signed, reflect.TypeOf(link)); err != nil {
return err
}

data, err := rawMb["signed"].MarshalJSON()
if err != nil {
return err
}
decoder := json.NewDecoder(strings.NewReader(string(data)))
decoder.DisallowUnknownFields()
if err := decoder.Decode(&link); err != nil {
return err
}
mb.Signed = link

} else if signed["_type"] == "layout" {
var layout Layout
if err := checkRequiredJSONFields(signed, reflect.TypeOf(layout)); err != nil {
return err
}

data, err := rawMb["signed"].MarshalJSON()
if err != nil {
return err
}
decoder := json.NewDecoder(strings.NewReader(string(data)))
decoder.DisallowUnknownFields()
if err := decoder.Decode(&layout); err != nil {
return err
}

mb.Signed = layout

} else {
return fmt.Errorf("the '_type' field of the 'signed' part of in-toto" +
" metadata must be one of 'link' or 'layout'")
}
mb.Signed = payload

return nil
}
Expand Down
4 changes: 2 additions & 2 deletions in_toto/model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func TestMetablockLoad(t *testing.T) {
"requires 'signed' and 'signatures' parts",
"cannot unmarshal string into Go value of type []in_toto.Signature",
"cannot unmarshal array into Go value of type map[string]interface {}",
"metadata must be one of 'link' or 'layout'",
ErrUnknownMetadataType.Error(),
"cannot unmarshal string into Go struct field Link.materials",
"cannot unmarshal string into Go struct field Layout.steps",
"required field steps missing",
Expand Down Expand Up @@ -1667,7 +1667,7 @@ func TestLoadMetadata(t *testing.T) {
"requires 'signed' and 'signatures' parts",
"cannot unmarshal string into Go value of type []in_toto.Signature",
"cannot unmarshal array into Go value of type map[string]interface {}",
"metadata must be one of 'link' or 'layout'",
ErrUnknownMetadataType.Error(),
"cannot unmarshal string into Go struct field Link.materials",
"cannot unmarshal string into Go struct field Layout.steps",
"required field steps missing",
Expand Down
43 changes: 43 additions & 0 deletions in_toto/util.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package in_toto

import (
"encoding/json"
"errors"
"fmt"
"reflect"
"strings"
)

var ErrUnknownMetadataType = errors.New("unknown metadata type encountered: not link or layout")

/*
Set represents a data structure for set operations. See `NewSet` for how to
create a Set, and available Set receivers for useful set operations.
Expand Down Expand Up @@ -145,3 +151,40 @@ func (s Set) IsSubSet(subset Set) bool {
}
return true
}

func loadPayload(payloadBytes []byte) (any, error) {
var payload map[string]any
if err := json.Unmarshal(payloadBytes, &payload); err != nil {
return nil, fmt.Errorf("error decoding payload: %w", err)
}

if payload["_type"] == "link" {
var link Link
if err := checkRequiredJSONFields(payload, reflect.TypeOf(link)); err != nil {
return nil, fmt.Errorf("error decoding payload: %w", err)
}

decoder := json.NewDecoder(strings.NewReader(string(payloadBytes)))
decoder.DisallowUnknownFields()
if err := decoder.Decode(&link); err != nil {
return nil, fmt.Errorf("error decoding payload: %w", err)
}

return link, nil
} else if payload["_type"] == "layout" {
var layout Layout
if err := checkRequiredJSONFields(payload, reflect.TypeOf(layout)); err != nil {
return nil, fmt.Errorf("error decoding payload: %w", err)
}

decoder := json.NewDecoder(strings.NewReader(string(payloadBytes)))
decoder.DisallowUnknownFields()
if err := decoder.Decode(&layout); err != nil {
return nil, fmt.Errorf("error decoding payload: %w", err)
}

return layout, nil
}

return nil, ErrUnknownMetadataType
}

0 comments on commit 4cbd94d

Please sign in to comment.