Create Algorithm Registry API#1601
Conversation
|
I'm working on some unit tests now. |
pkg/signature/algorithm_registry.go
Outdated
| return a.hashType == hashType | ||
| } | ||
|
|
||
| var algorithmDetails = []algorithmDetailsImpl{ |
There was a problem hiding this comment.
I moved away from that design where I had an interface and an implementation for each signature algorithm as it was really doing anything for us. Each AlgorithmRegistryConfig now holds pointers to algorithms in this list.
pkg/signature/algorithm_registry.go
Outdated
| return fmt.Errorf("signing algorithm not permitted: %T, %s", key, hash) | ||
| } | ||
|
|
||
| // FormatSignatureAlgorithmFlag formats a v1.KnownSignatureAlgorithm to a string that conforms to the conventions of CLI |
There was a problem hiding this comment.
This CLI stuff isn't terribly efficient but I don't expect it to be on the hot path since this is just initialisation code.
|
CC: @ret2libc @woodruffw @haydentherapper |
9eec947 to
1be7204
Compare
|
@tetsuo-cpp you can see https://github.com/trail-of-forks/cosign/compare/support-ed25519ph...trail-of-forks:cosign:signing-algorithm-flag?expand=1 on how I might be using the registry in cosign. Hope it helps us define a good API! |
5b727de to
dfb835b
Compare
|
(Force-pushed to fix the signoffs.) |
pkg/signature/algorithm_registry.go
Outdated
| } | ||
|
|
||
| // IsAlgorithmPermitted checks whether a given public key/hash algorithm combination is permitted by a registry config. | ||
| func (registryConfig AlgorithmRegistryConfig) IsAlgorithmPermitted(key crypto.PublicKey, hash crypto.Hash) bool { |
There was a problem hiding this comment.
How do you foresee this being used with KMS keys? Should the caller be required to inspect the KMS key for its key and hash (we have key, we're missing hash, but it's being implemented in #1426). Should each KMS provider has its own registry?(as a service, this would be a bit annoying to use, since you'd have to consult a registry of regstries)
There was a problem hiding this comment.
I think it makes most sense for the calling code to inspect the KMS key and hash, and check against the registry to see whether it should use that key or not.
I don't think it makes sense for each KMS provider to own its own registry, but perhaps the kms.SignerVerifier API could take an optional AlgorithmRegistryConfig and do the checking there? But I'd lean towards not tangling the APIs together like that and just let the calling code compose these calls as required.
What are your thoughts?
There was a problem hiding this comment.
That sounds good to me. Long-term I'd lean towards the proposal to take in a config, just to avoid each client having to reimplement this, but I don't think it's something that's blocking regardless, just thinking through how we'll handle users who provide their own KMS keys.
pkg/signature/algorithm_registry.go
Outdated
| } | ||
|
|
||
| // IsAlgorithmPermitted checks whether a given public key/hash algorithm combination is permitted by a registry config. | ||
| func (registryConfig AlgorithmRegistryConfig) IsAlgorithmPermitted(key crypto.PublicKey, hash crypto.Hash) bool { |
There was a problem hiding this comment.
That sounds good to me. Long-term I'd lean towards the proposal to take in a config, just to avoid each client having to reimplement this, but I don't think it's something that's blocking regardless, just thinking through how we'll handle users who provide their own KMS keys.
pkg/signature/algorithm_registry.go
Outdated
| // GetAlgorithmDetails retrieves a set of details for a given v1.KnownSignatureAlgorithm flag that allows users to | ||
| // introspect the public key algorithm, hash algorithm and more. | ||
| func GetAlgorithmDetails(knownSignatureAlgorithm v1.KnownSignatureAlgorithm) (AlgorithmDetails, error) { | ||
| for _, detail := range algorithmDetails { |
There was a problem hiding this comment.
maybe turn this into a map[v1.KnownSignatureAlgorithm]AlgorithmDetails ?
There was a problem hiding this comment.
I was thinking about this, but my reasons not to were:
- If I do that, I have to match the
v1.KnownSignatureAlgorithmin theAlgorithmDetailswith the one in the map key, which is another opportunity for subtle typos that can introduce bugs. I can't remove it fromAlgorithmDetailssince we need it for things likeAlgorithmRegistryConfig.ListPermittedAlgorithms. - The
algorithmDetailsarray only includes an entry for each signature algorithm in the registry which by design, is a small, constrained set of algorithms. I haven't benchmarked and to be honest, I don't know much about Go's performance characteristics, but I wouldn't expect the map to be faster than a simple linear search for this number of elements. - This array isn't part of the public API so if my assumptions are wrong in the long term, we can easily walk this decision back if we need to without introducing breaking changes.
Happy to change it over to a map, if you'd prefer though.
Hayden-IO
left a comment
There was a problem hiding this comment.
Overall LGTM, please take a look at the lint failure
| if err != nil { | ||
| t.Errorf("unexpected error creating algorithm registry config: %v", err) | ||
| } | ||
|
|
There was a problem hiding this comment.
Can we also add a test for RSA keys being permitted?
It might be overkill, but ideally we'd have a test for every supported key type, to have maximum code coverage.
|
@kommendorkapten Do you want to take a look at this PR? There's an open question of how this should interact with |
|
This is great 🚀 I believe there is an overlap between
The only differences I see is the naming, and that One can argue that the two types might solve slightly different problems, but as the overlap is so big, I would feel better if they could be combined, otherwise the clients would need to translate between the two formats, which I feel is sub-optimal. Thoughts? |
Aren't the RSA values also missing the hash algorithm, or is that implied somehow? That was the main reason I didn't add to If it's fine to overwrite the values in |
I don't remember the reason we left the RSA values underspecified 🤔 , but adding new values with them in there would make no harm. Yeah, adding the new values missing in |
That seems reasonable. I had another idea though: what do you think about marking the entire |
@haydentherapper you can see its use in other pending PRs like sigstore/rekor#1974 , sigstore/cosign#3497 , sigstore/fulcio#1517 (this last one might be outdated) |
d548633 to
e6f153b
Compare
4b47bc2 to
51e2bd0
Compare
Signed-off-by: Riccardo Schirone <[email protected]> Signed-off-by: Alex Cameron <[email protected]> Signed-off-by: William Woodruff <[email protected]> Co-authored-by: Alex Cameron <[email protected]> Co-authored-by: Riccardo Schirone <[email protected]>
51e2bd0 to
9b265f4
Compare
ret2libc
left a comment
There was a problem hiding this comment.
I have squashed the whole history into 1 commit because there were very old iterations that did not make sense anymore.
The PR was tested with fulcio/rekor/cosign.
With regards to the API and its uses: to be honest a few functions are not used anywhere, so we may make the API even smaller and hide more things, if we want. So if/when it grows/changes it will be easier to do so.
In particular, these functions are not used in any of the other components:
- HasAlgorithmDetails
- ListPermittedAlgorithms
- registry.GetAlgorithmDetails
- GetAlgorithmDetails
|
ping @haydentherapper There has been a lot of back and forth on this PR and the others. I have updated all of them, so I'd appreciate a new review on this. |
|
Thanks @ret2libc for the updates! I did a review over the PR and reviewed my old comments to remember where we had ended - I think the PR is looking good! For those functions, if they're unused, I'd agree that we can omit then. I'd rather keep the API surface smaller and expand it later as needed. Do you recall why we had proposed those? It seems like those are mostly focused on exposing the configuration mapping, which I assume would only be relevant to developers who could inspect the source code. |
I think they were just exposed to have a "nice API" and maybe also because we did not know how we would have ended up using the API when we started with this. I'm going to clean the API! |
Signed-off-by: Riccardo Schirone <[email protected]>
Signed-off-by: Riccardo Schirone <[email protected]>
Signed-off-by: Riccardo Schirone <[email protected]>
Signed-off-by: Riccardo Schirone <[email protected]>
Signed-off-by: Riccardo Schirone <[email protected]>
Hayden-IO
left a comment
There was a problem hiding this comment.
This looks great! Any other changes or is this good to merge?
Signed-off-by: Riccardo Schirone <[email protected]>
Signed-off-by: Riccardo Schirone <[email protected]>
Signed-off-by: Riccardo Schirone <[email protected]>
|
Going to merge now, thanks all! |
Summary
As part of our work to support configurable crypto algorithms across the Sigstore stack, we've added a
KnownSignatureAlgorithmenumeration toprotobuf-specsto reflect what signature algorithms are part of the official Sigstore algorithm registry. This PR adds some helpers and APIs to make use of this registry in Sigstore services.Release Note
GetAlgorithmDetailshelper to access the key algorithm, hash algorithm and other algorithm-specific parameters for a given signature algorithm.AlgorithmRegistryConfigAPI to check a public key and hash algorithm combination against a set of accepted signature algorithms.FormatSignatureAlgorithmFlagandParseSignatureAlgorithmFlagto convert the signature algorithm type to and from a string representation that can be used as a CLI parameter.Documentation