Skip to content

Commit

Permalink
Remove requirement of PayloadHash for intoto 0.0.1 (#1490)
Browse files Browse the repository at this point in the history
* Remove requirement of PayloadHash for intoto 0.0.1

The payload hash was added later on, so old committed entries are
missing the payload hash. This means that canonicalization will fail
when searching for the entry if we require the payload hash.

Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>

* add e2e test

Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>

---------

Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
  • Loading branch information
haydentherapper authored May 24, 2023
1 parent b387701 commit d508eba
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 11 deletions.
32 changes: 32 additions & 0 deletions pkg/types/intoto/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,3 +394,35 @@ func TestValidationSearchIntotoV002MissingPayloadHash(t *testing.T) {
t.Fatalf("expected status 400, got %d instead: %v", resp.StatusCode, string(c))
}
}

func TestValidationSearchIntotoV001MissingPayloadHash(t *testing.T) {
body := `{
"entries":[
{
"kind":"intoto",
"apiVersion": "0.0.1",
"spec":{
"content":{
"hash":{
"algorithm":"sha256",
"value":"ebbfddda6277af199e93c5bb5cf5998a79311de238e49bcc8ac24102698761bb"
}
},
"publicKey":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNwRENDQWlxZ0F3SUJBZ0lVYWhsOEFRd1lZV05ZbnV6dlFvOEVrN1dMTURvd0NnWUlLb1pJemowRUF3TXcKTnpFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNUjR3SEFZRFZRUURFeFZ6YVdkemRHOXlaUzFwYm5SbApjbTFsWkdsaGRHVXdIaGNOTWpJd09ESTJNREV4TnpFM1doY05Nakl3T0RJMk1ERXlOekUzV2pBQU1Ga3dFd1lICktvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVLWmZEQzlpalVyclpBWE9jWFYrQXFHRUlTSlEzVHRqSndJdEEKdTE3Rml2aWpnSk1hYUhGNDcrT3Z2OVR1ekFDQ3lpSUV5UDUyZXI2ZmF5bmZKYVVqOEtPQ0FVa3dnZ0ZGTUE0RwpBMVVkRHdFQi93UUVBd0lIZ0RBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREF6QWRCZ05WSFE0RUZnUVVHQldUCkMwdUU3dTRQcURVRjFYV0c0QlVWVUpBd0h3WURWUjBqQkJnd0ZvQVUzOVBwejFZa0VaYjVxTmpwS0ZXaXhpNFkKWkQ4d0pRWURWUjBSQVFIL0JCc3dHWUVYYzJGemIyRnJhWEpoTmpFeE5FQm5iV0ZwYkM1amIyMHdLUVlLS3dZQgpCQUdEdnpBQkFRUWJhSFIwY0hNNkx5OWhZMk52ZFc1MGN5NW5iMjluYkdVdVkyOXRNSUdMQmdvckJnRUVBZFo1CkFnUUNCSDBFZXdCNUFIY0FDR0NTOENoUy8yaEYwZEZySjRTY1JXY1lyQlk5d3pqU2JlYThJZ1kyYjNJQUFBR0MKMTdtSmhnQUFCQU1BU0RCR0FpRUFoS09BSkdWVlhCb1cxTDR4alk5eWJWOGZUUXN5TStvUEpIeDk5S29LYUpVQwpJUURCZDllc1Q0Mk1STng3Vm9BM1paKzV4akhNZWR6amVxQ2ZoZTcvd1pxYTlUQUtCZ2dxaGtqT1BRUURBd05vCkFEQmxBakVBcnBkeXlFRjc3b2JyTENMUXpzYmIxM2lsNjd3dzM4Y050amdNQml6Y2VUakRiY2VLeVFSN1RKNHMKZENsclkxY1BBakE4aXB6SUQ4VU1CaGxkSmUvZXJGcGdtN2swNWFic2lPN3V5dVZuS29VNk0rTXJ6VVUrZTlGdwpJRGhCanVRa1dRYz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo="
}
}
]
}
`
resp, err := http.Post(fmt.Sprintf("%s/api/v1/log/entries/retrieve", rekorServer()),
"application/json",
bytes.NewBuffer([]byte(body)))
if err != nil {
t.Fatal(err)
}
c, _ := ioutil.ReadAll(resp.Body)
// No failure when payload hash is not present for canonicalization
if resp.StatusCode != 200 {
t.Fatalf("expected status 200, got %d instead: %v", resp.StatusCode, string(c))
}
}
25 changes: 14 additions & 11 deletions pkg/types/intoto/v0.0.1/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,8 @@ func (v *V001Entry) Canonicalize(_ context.Context) ([]byte, error) {
if v.IntotoObj.Content.Hash == nil {
return nil, errors.New("missing envelope hash")
}
if v.IntotoObj.Content.PayloadHash == nil {
return nil, errors.New("missing payload hash")
}
// PayloadHash is not present for old entries

pk, err := v.keyObj.CanonicalValue()
if err != nil {
return nil, err
Expand All @@ -209,12 +208,15 @@ func (v *V001Entry) Canonicalize(_ context.Context) ([]byte, error) {
Algorithm: v.IntotoObj.Content.Hash.Algorithm,
Value: v.IntotoObj.Content.Hash.Value,
},
PayloadHash: &models.IntotoV001SchemaContentPayloadHash{
Algorithm: v.IntotoObj.Content.PayloadHash.Algorithm,
Value: v.IntotoObj.Content.PayloadHash.Value,
},
},
}
// Set PayloadHash if present
if v.IntotoObj.Content.PayloadHash != nil {
canonicalEntry.Content.PayloadHash = &models.IntotoV001SchemaContentPayloadHash{
Algorithm: v.IntotoObj.Content.PayloadHash.Algorithm,
Value: v.IntotoObj.Content.PayloadHash.Value,
}
}

itObj := models.Intoto{}
itObj.APIVersion = swag.String(APIVERSION)
Expand All @@ -237,10 +239,11 @@ func (v *V001Entry) validate() error {
} else if err := v.IntotoObj.Content.Hash.Validate(strfmt.Default); err != nil {
return fmt.Errorf("validation error on envelope hash: %w", err)
}
if v.IntotoObj.Content.PayloadHash == nil {
return fmt.Errorf("missing hash value for payload")
} else if err := v.IntotoObj.Content.PayloadHash.Validate(strfmt.Default); err != nil {
return fmt.Errorf("validation error on payload hash: %w", err)
// PayloadHash is not present for old entries
if v.IntotoObj.Content.PayloadHash != nil {
if err := v.IntotoObj.Content.PayloadHash.Validate(strfmt.Default); err != nil {
return fmt.Errorf("validation error on payload hash: %w", err)
}
}
// if there is no envelope, and hash/payloadHash are valid, then there's nothing else to do here
return nil
Expand Down
37 changes: 37 additions & 0 deletions pkg/types/intoto/v0.0.1/entry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,43 @@ func TestV001Entry_Unmarshal(t *testing.T) {
}
}

// Demonstrates that Unmarshal and Canonicalize will succeed with only a hash,
// since committed entries will have no envelope and may have no payload hash
func TestV001EntryWithoutEnvelopeOrPayloadHash(t *testing.T) {
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
t.Fatal(err)
}
der, err := x509.MarshalPKIXPublicKey(&key.PublicKey)
if err != nil {
t.Fatal(err)
}
pub := pem.EncodeToMemory(&pem.Block{
Bytes: der,
Type: "PUBLIC KEY",
})
m := &models.IntotoV001Schema{
PublicKey: p(pub),
Content: &models.IntotoV001SchemaContent{
Hash: &models.IntotoV001SchemaContentHash{
Algorithm: swag.String(models.IntotoV001SchemaContentHashAlgorithmSha256),
Value: swag.String("1a1707bb54e5fb4deddd19f07adcb4f1e022ca7879e3c8348da8d4fa496ae8e2"),
},
},
}
v := &V001Entry{}
it := &models.Intoto{
Spec: m,
}
if err := v.Unmarshal(it); err != nil {
t.Fatalf("error umarshalling intoto without envelope: %v", err)
}
_, err = v.Canonicalize(context.TODO())
if err != nil {
t.Fatalf("error canonicalizing intoto without envelope: %v", err)
}
}

func TestV001Entry_IndexKeys(t *testing.T) {
h := sha256.Sum256([]byte("foo"))
dataSHA := hex.EncodeToString(h[:])
Expand Down

0 comments on commit d508eba

Please sign in to comment.