UUID parsing to include pre-pended shard ID#515
UUID parsing to include pre-pended shard ID#515lkatalin wants to merge 1 commit intosigstore:mainfrom
Conversation
|
@lukehinds @asraa @bobcallaway @dlorenc |
cmd/rekor-cli/app/pflags.go
Outdated
| return valueFactory(uuidFlag, validateString("required,len=64,hexadecimal"), "") | ||
| // this corresponds to the merkle leaf hash of entries, which is represented by a 64 character hexadecimal string, prepended by the 6-digit shard ID and '-' separator | ||
| // TODO: does this have to be a literal? can we not use the const to define the len? | ||
| // TODO: is there a way to validate only the UUID part of this string as hexadecimal? or validate different parts of the string differently? can / should they be split into different flags? |
There was a problem hiding this comment.
you could make a custom validator! instead of validateString you could make validateShardedUUID with a custom impl like the ones found here
rekor/cmd/rekor-cli/app/pflags.go
Line 170 in 5025a24
There was a problem hiding this comment.
Thank you @asraa ! That's exactly what I want to do. I appreciate the example.
pkg/api/entries.go
Outdated
|
|
||
| queuedLeaf := resp.getAddResult.QueuedLeaf.Leaf | ||
| uuid := hex.EncodeToString(queuedLeaf.GetMerkleLeafHash()) | ||
| shardID := "000000" |
There was a problem hiding this comment.
is the thought that the shardID would be a base10 integer or base16 (hex) like the rest of the UUID?
There was a problem hiding this comment.
@bobcallaway I was going to have it as a base10 integer so that it's more easily human-readable, but I'm definitely open to suggestions here. Is there an advantage to having it in hex?
|
I've got an updated version here that
Outstanding todos:
|
|
Also, I am not sure whether it is normal with go code to have |
That's fine, its different to cargo where you tend to only push the toml file. |
9935f6d to
2c88ec8
Compare
2c88ec8 to
d55d754
Compare
|
I think this is almost ready for review, but I'm not sure how to reproduce the failing e2e test locally (and therefore figure out what's going on with it). It seems to pass: |
|
Could be a flake if it passes locally trying to re-run it now. The other thing to try might be making sure you're fully rebased. |
Hmm, I had rebased on main last night before running the tests and I just did so again. Puzzling. |
cmd/rekor-cli/app/pflags.go
Outdated
|
|
||
| // validate the ShardID | ||
| shardID := v[:sharding.ShardIDLen] | ||
| shardIDTag := "required," + "len=" + fmt.Sprintf("%v", sharding.ShardIDLen) + ",number" |
There was a problem hiding this comment.
nit: is there a reason this is not shardIDTag := "required, len=" + fmt.Sprintf("%v",?
Ditto for L215
There was a problem hiding this comment.
@jeffvance No, there isn't. : ) Thanks for the catch, I will update this.
af3e1bc to
1f7be40
Compare
|
It does look like it's an empty attestation on the failing test: |
|
I've managed to reproduce this locally! Sorry it took a bit longer than expected, I'm on a new M1 Macbook and it took a bit to get the dev environment running there. --- FAIL: TestIntoto (0.52s)
e2e_test.go:439: g.Attesation: []
e2e_test.go:443: unexpected end of JSON input
FAIL
FAIL github.com/sigstore/rekor/tests 0.710s
FAILI think I have a guess at the issue... |
| queuedLeaf := resp.getAddResult.QueuedLeaf.Leaf | ||
| uuid := hex.EncodeToString(queuedLeaf.GetMerkleLeafHash()) | ||
| shardID := sharding.NewCurrent() | ||
| uuid := shardID.ShardIDString + sharding.FullIDSeparator + hex.EncodeToString(queuedLeaf.GetMerkleLeafHash()) |
There was a problem hiding this comment.
I think we need to make this a helper function, and call it anywhere we go from a MerkleLeafHash to a UUID.
To fix the e2e test, we also need it right here: https://github.com/sigstore/rekor/blob/main/pkg/api/entries.go#L95
There was a problem hiding this comment.
@dlorenc I can change it to a helper function, that's a great idea.
Thank you for figuring out what's going on with the e2e test!
|
OK, got a passing test over here! #548 I think I see the issue now. Let me know if you want to chat a bit more this week, I have a few ideas. |
Thanks @dlorenc , I really appreciate you looking into it. I still need to understand how the changes you suggested are related to the e2e test. I'm also happy to incorporate those changes in whatever way you think is best to get this to pass CI and merge it asap. |
At a high level it's just a case of confusion between The In-Toto Attestations are stored separately from the Transparency Log itself, to make them redactable if we ever need to. The failing test tests that behavior. The change in entries.go fixes that up so we retrieve it by the UUID instead of the The change in get.go is unnecessary, but helped me when debugging and is otherwise safe. You can drop it if you prefer and we can handle that one separately. |
| // TODO: The shardID will be part of the state and will be updated. Store it in state.go? | ||
| // TODO: Add a check that the CurrentShardID cannot be updated beyond 999,999 | ||
|
|
||
| var CurrentShardID uint32 = 0 |
There was a problem hiding this comment.
I think this will need to be passed or parsed out of the log index range flag, it would basically be the last one in the list: https://github.com/sigstore/rekor/blob/main/cmd/rekor-server/app/flags.go#L29
The client shouldn't need to know the active shard id - it's purely controlled server side by that flag.
There was a problem hiding this comment.
Thanks, I will use the ActiveIndex() from here #549
| } | ||
|
|
||
| // Create a 6-digit string from shardID | ||
| func IntToString(i uint32) string { |
There was a problem hiding this comment.
You can use strconv.ParseInt here, it'll also handle the error cases.
| metricNewEntries.Inc() | ||
|
|
||
| queuedLeaf := resp.getAddResult.QueuedLeaf.Leaf | ||
| uuid := hex.EncodeToString(queuedLeaf.GetMerkleLeafHash()) |
There was a problem hiding this comment.
Actually, I'm not 100% sure this change is safe as is - I don't think it would be backwards compatible (we need a test for this). It means the server would start returning the shard-prefixed UUID to clients who create one - but older clients wouldn't have the change you added in here to get.go.
Older clients would then have a UUID that's invalid to them. I think we might need to drop this part for a release or two, to make sure clients can handle the new format.
There was a problem hiding this comment.
Interesting, I had not considered that older clients might still be used. I can write a test to make sure this will work when we include it.
This should help out with sigstore#515. Signed-off-by: Dan Lorenc <lorenc.d@gmail.com>
This should help out with sigstore#515. Signed-off-by: Dan Lorenc <lorenc.d@gmail.com>
Signed-off-by: Lily Sturmann <lsturman@redhat.com>
1f7be40 to
2819f5a
Compare
@dlorenc Thank you for this explanation - I had totally missed that there is another part of the code using the |
|
I'm still making changes to this. |
This should help out with #515. Signed-off-by: Dan Lorenc <lorenc.d@gmail.com>
| } else if len(uuid) == sharding.FullIDLen { | ||
| params.EntryUUID = uuid[sharding.FullIDLen-sharding.UUIDLen:] | ||
| } else { | ||
| return nil, fmt.Errorf("invalid UUID length: %v", len(uuid)) |
There was a problem hiding this comment.
should we augment this error message to tell the user what the valid length/format should be?
| continue | ||
| } | ||
|
|
||
| // TODO: understand why we don't need k to match params.EntryUUID |
There was a problem hiding this comment.
k should match the UUID returned but as Dan mentioned in his other review comment there would be a concern about backward compatibility.
| if len(uuid) == sharding.UUIDLen { | ||
| params.EntryUUID = uuid | ||
| } else if len(uuid) == sharding.FullIDLen { | ||
| params.EntryUUID = uuid[sharding.FullIDLen-sharding.UUIDLen:] | ||
| } else { | ||
| return nil, fmt.Errorf("invalid UUID length: %v", len(uuid)) |
There was a problem hiding this comment.
also, if you end up writing a helper method for creating this within the sharding package then would it make sense to move the validation logic in there, as well as add a new helper method to parse the input?
Summary
This is a draft! Feedback welcome, including overall design considerations. I've got some to-dos that I am still sorting out as listed here and in code comments. It's not many lines of code, but I did a fair amount of experimentation to get to this point as it's my first "real" Rekor PR. : )
Here is how it's working currently:
Ticket Link
Fixes #487
Release Note
pflags.goandopenapi.yaml? I'm looking into this.