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

Add COSE support to Rekor #867

Merged
merged 14 commits into from
Jun 23, 2022
Merged

Add COSE support to Rekor #867

merged 14 commits into from
Jun 23, 2022

Conversation

kommendorkapten
Copy link
Member

Summary

Basic support for COSE envelopes.
Added is functionality to upload COSE records, optionally signed with AAD. The AAD is not stored in Rekor.
The COSE envelope is stored as an attestation if attestation storage is enabled, and can so be retrieved via Rekor. The returned envelope is returned in the attestation field, not within the body field.

What's stored is the hash of the payload and the entire envelope. If the content type of the COSE envelope is an in-toto statement, the payload is parsed and the subject hashes are extracted and indexed for searching.

Ticket Link

This pull requests completes #731.

Release Note

Added new request/response type: COSE envelopes. When uploading a COSE envelope, only the hash of the payload and the hash of the envelope is stored, unless attestation storage is enabled, then the entire envelope is stored as an attestation.
A new command line parameter `--aad` is added. This parameter provides extra Additional Authenticated Data to be used during COSE signature verification (using AAD with COSE is optional).

@kommendorkapten kommendorkapten requested review from bobcallaway and a team as code owners June 9, 2022 08:37
@kommendorkapten kommendorkapten changed the title Add cose Add COSE support to Rekor Jun 9, 2022
@dlorenc
Copy link
Member

dlorenc commented Jun 9, 2022

Looks like there's a merge conflict, and github isn't running for some reason. Maybe fixing the merge conflict will poke actions?

@kommendorkapten
Copy link
Member Author

Yes, will do. Some merge conflicts I have to resolve first 👍

@kommendorkapten kommendorkapten force-pushed the add_cose branch 2 times, most recently from 30fcf43 to c3180ed Compare June 10, 2022 07:59
Copy link
Member

@dlorenc dlorenc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One main question on algorithm checking.

switch t := cryptoPub.(type) {
case *rsa.PublicKey:
alg = gocose.AlgorithmPS256
case *ecdsa.PublicKey:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to be a bit more careful here to avoid curve mismatches? Is there a possibility someone actually used PS384 or PS512?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good catch. I can play around a bit more early next week to see if we can tighten up this.

}

// If payload is an in-toto statement, let's grab the subjects.
if rawContentType, ok := v.sign1Msg.Headers.Protected[gocose.HeaderLabelContentType]; ok {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part is interesting, I'm not sure I've seen in-toto statements embedded into COSE envelopes before. I think it makes sense overall though.

@codecov-commenter
Copy link

codecov-commenter commented Jun 13, 2022

Codecov Report

Merging #867 (142be5b) into main (45da1af) will increase coverage by 0.69%.
The diff coverage is 59.92%.

@@            Coverage Diff             @@
##             main     #867      +/-   ##
==========================================
+ Coverage   46.24%   46.93%   +0.69%     
==========================================
  Files          60       62       +2     
  Lines        5138     5414     +276     
==========================================
+ Hits         2376     2541     +165     
- Misses       2487     2590     +103     
- Partials      275      283       +8     
Impacted Files Coverage Δ
cmd/rekor-cli/app/root.go 20.68% <ø> (ø)
pkg/types/entries.go 6.25% <ø> (ø)
pkg/types/test_util.go 0.00% <0.00%> (ø)
pkg/types/cose/v0.0.1/entry.go 54.22% <54.22%> (ø)
cmd/rekor-cli/app/pflag_groups.go 87.20% <100.00%> (+0.87%) ⬆️
cmd/rekor-cli/app/pflags.go 85.33% <100.00%> (+0.82%) ⬆️
pkg/types/cose/cose.go 100.00% <100.00%> (ø)
pkg/types/alpine/v0.0.1/entry.go 54.54% <0.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 45da1af...142be5b. Read the comment docs.

@dlorenc
Copy link
Member

dlorenc commented Jun 13, 2022

Overall LGTM. I'll wait for @bobcallaway to take a look before merging.

1 similar comment
@dlorenc
Copy link
Member

dlorenc commented Jun 13, 2022

Overall LGTM. I'll wait for @bobcallaway to take a look before merging.

Copy link
Member

@bobcallaway bobcallaway left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking good overall, just a few questions/nits

cmd/rekor-cli/app/pflag_groups.go Outdated Show resolved Hide resolved
pkg/types/cose/cose.go Outdated Show resolved Hide resolved
go.mod Outdated Show resolved Hide resolved
pkg/types/cose/cose.go Outdated Show resolved Hide resolved

alg, pk, err := getPublicKey(v.keyObj)
if err != nil {
return nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you mean to return err here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course, will go over some test coverage here to make sure we got it covered.

Comment on lines 243 to 246
v.sign1Msg = gocose.NewSign1Message()
if err := v.sign1Msg.UnmarshalCBOR(v.CoseObj.Message); err != nil {
return err
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we ensure unmarshaling is successful before assigning the output to v.sign1Msg?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean like this:

        coseMsg := gocose.NewSign1Message()
	if err := coseMsg.UnmarshalCBOR(v.CoseObj.Message); err != nil {
		return err
	}
        v.sign1Msg = coseMsg

I think that makes sense, we can even wait until the signature is verified until we assign it to v.sign1Msg.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, ideally I wouldn't want to partially change the pointer receiver unless all validation is successful.

pkg/types/entries.go Outdated Show resolved Hide resolved
Copy link
Member

@bobcallaway bobcallaway left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, would like one more test case to ensure we have coverage for non-base64 encoded input on the aad cmd line argument

cmd/rekor-cli/app/pflags_test.go Show resolved Hide resolved
bobcallaway
bobcallaway previously approved these changes Jun 14, 2022
@kommendorkapten
Copy link
Member Author

kommendorkapten commented Jun 14, 2022

The sharding e2e test failed (curl: (22) The requested URL returned error: 422 Unprocessable Entity). Is there any documentation on running this locally?

@kommendorkapten
Copy link
Member Author

Oh, found a script, will try that.

@kommendorkapten
Copy link
Member Author

I have run the sharding-e2e test now locally three times and am not able to reproduce, the execution succeeds all the time for me. Anyone having an idea?

@kommendorkapten
Copy link
Member Author

kommendorkapten commented Jun 14, 2022

Hm, this seems to be the issue:

++ printf %x 7051007558037933689
++ Awk '{printf "%016s", $0}'
+ HEX_INITIAL_TREE_ID=61da360425720e79
++ printf %x 151938258151519870
++ awk '{printf "%016s", $0}'
+ HEX_INITIAL_SHARD_ID=' 21bcb0a70e9b67e'
+ ENTRY_ID_1=61da360425720e79d2f305428d7c222d7b77f56453dd4b6e6851752ecacc78e5992779c8f9b61dd9
+ ENTRY_ID_2=' 21bcb0a70e9b67e59a575f157274702c38de3ab1e1784226f391fb79500ebf9f02b4439fb77574c'
++ curl -f http://localhost:3000/api/v1/log/entries/retrieve -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{ "entryUUIDs": ["61da360425720e79d2f305428d7c222d7b77f56453dd4b6e6851752ecacc78e5992779c8f9b61dd9", " 21bcb0a70e9b67e59a575f157274702c38de3ab1e1784226f391fb79500ebf9f02b4439fb77574c"]}'
++ jq '. | length'

The shard id gets a white space ( ) as the first character, which is then input to the UUIDs: " 21bcb0a70e9b67e59a575f157274702c38de3ab1e1784226f391fb79500ebf9f02b4439fb77574c".

Running the printf/awk on my machine (macOS) I get a different output

 printf %x 151938258151519870 | awk '{printf "%016s", $0}'
021bcb0a70e9b67e

Running same command on Ubuntu:

# printf %x 151938258151519870 | awk '{printf "%016s", $0}'
 21bcb0a70e9b67e

I'll prepare a patch for the awk script.

@bobcallaway
Copy link
Member

bobcallaway commented Jun 14, 2022 via email

@kommendorkapten
Copy link
Member Author

From the GNU awk manual (https://www.gnu.org/software/gawk/manual/html_node/Format-Modifiers.html): (emphasis mine)

A leading ‘0’ (zero) acts as a flag indicating that output should be padded with zeros instead of spaces. This applies only to the numeric output formats. This flag only has an effect when the field width is wider than the value to print.

@kommendorkapten
Copy link
Member Author

kommendorkapten commented Jun 14, 2022

Shamelessly copied this from stackoverflow (some minor modification to work with printf instead of echo):

printf abc123 | awk '{ for(c = 0; c < 16 ; c++) s = s"0"; s = s$1; print substr(s, 1 + length(s) - 16);}'
0000000000abc123

Tested on both Ubuntu and macOS

@bobcallaway
Copy link
Member

Shamelessly copied this from stackoverflow (some minor modification to work with printf instead of echo):

printf abc123 | awk '{ for(c = 0; c < 16 ; c++) s = s"0"; s = s$1; print substr(s, 1 + length(s) - 16);}'
0000000000abc123

Tested on both Ubuntu and macOS

@priyawadhwa @lkatalin is the intent for the value to be left-padded with zeros?

@lkatalin
Copy link
Contributor

@priyawadhwa @lkatalin is the intent for the value to be left-padded with zeros?

@bobcallaway
Still going through trying to understand this error, but the padding is something I had included so that we can get a consistent length, probably so that we can easily parse the TreeID from the UUID.

dlorenc and others added 6 commits June 21, 2022 07:40
This commit adds COSE Sign1 support to rekor via a new data type.
COSE is defined in RFC8152, and provides a signing message envelope.

This is supported in rekor using the veraison/go-cose library. The new
API type requires the signed content, the signature envelope, and the public key.

The public key is in the standard rekor PKI format, at the moment only ECDSA P256
with SHA256 is supported. The signed message only supports in-line bodies (no URL fetching),
and there is no support for pre-hashed entries.

Signed-off-by: Dan Lorenc <lorenc.d@gmail.com>
This adds some more functionality related to COSE enveleopes.
Features added are:

 - Support for specifying Additional Authentincated Data (AAD)

 - The entire CBOR envelope is stored as an attestation

 - If the payload type is an in-toto statement, subject is indexed

What's not optimal is that the COSE envelope is using the regular
`Attestion()` functionality, which means that rekor cli tries to
print it during `rekor-cli get` and the response record from Rekor
looks a bit awkward.

Signed-off-by: Fredrik Skogman <kommendorkapten@github.com>
Signed-off-by: Fredrik Skogman <kommendorkapten@github.com>
The biggest change is adapting the new interface where attestation func
is split to two, one to get the key and a nother to get key/val.

Signed-off-by: Fredrik Skogman <kommendorkapten@github.com>
Signed-off-by: Fredrik Skogman <kommendorkapten@github.com>
Signed-off-by: Fredrik Skogman <kommendorkapten@github.com>
Signed-off-by: Fredrik Skogman <kommendorkapten@github.com>
Signed-off-by: Fredrik Skogman <kommendorkapten@github.com>
…stdlib

errors package.

Signed-off-by: Fredrik Skogman <kommendorkapten@github.com>
Also increas the general test coverage.

Signed-off-by: Fredrik Skogman <kommendorkapten@github.com>
…ing.

This gives the caller the possibility to decide how to decode the data.

Signed-off-by: Fredrik Skogman <kommendorkapten@github.com>
Signed-off-by: Fredrik Skogman <kommendorkapten@github.com>
Signed-off-by: Fredrik Skogman <kommendorkapten@github.com>
…dation

is done.

Signed-off-by: Fredrik Skogman <kommendorkapten@github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants