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

Signing config cleanup #2420

Merged
merged 2 commits into from
Oct 10, 2023
Merged

Signing config cleanup #2420

merged 2 commits into from
Oct 10, 2023

Conversation

moskyb
Copy link
Contributor

@moskyb moskyb commented Oct 10, 2023

Closes: PDP-1764

This PR: Makes three changes to the way pipeline signing is configured:

  • It removes the --signing-algorithm option, and the way that it would inject the algorithm into keys. As such, the alg key is now mandatory in signing JWKs
  • It makes --signing-key-id optional. If one is provided, then the agent will use the signing key referred to by that ID, if it's present. If no signing key id is provided, the agent will use the first key in the JWKS. When verifyinh, the jwx library will just try every key in the verification key set This has been reverted, key IDs are now mandatory again
  • It collapses the two flags --job-verification-no-signature-behavior and --job-verification-invalid-signature-behavior into one combined flag, --job-verification-failure-behaviour. This is simpler and a lot less wordy.

Comment on lines +1117 to +1108
iter := jwks.Keys(ctx)
for iter.Next(ctx) {
keyI := iter.Pair().Value
key, ok := keyI.(jwk.Key)
if !ok {
return nil, fmt.Errorf("Job %s keyset contains a non-key at index %d", keysetType, iter.Pair().Index)
}
Copy link
Contributor Author

@moskyb moskyb Oct 10, 2023

Choose a reason for hiding this comment

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

it's deeply odd to me that the iterator for the jwk.Set type (which can only contain jwk.Keys) returns an int index and an any key, but ¯\_(ツ)_/¯

Comment on lines -436 to -473
func injectAlgorithm(key jwk.Key, cfg PipelineUploadConfig) error {
keyHasAlgorithm := key.Algorithm() != nil && key.Algorithm().String() != ""

var alg jwa.KeyAlgorithm
var from string // for error messages
switch {
case !keyHasAlgorithm && cfg.SigningAlgorithm == "":
return fmt.Errorf("signing algorithm is required if JWKS key doesn't have an alg parameter")

case keyHasAlgorithm && cfg.SigningAlgorithm != "":
return fmt.Errorf("signing algorithm is not allowed if JWKS key has an alg parameter")

case cfg.SigningAlgorithm != "":
alg = jwa.SignatureAlgorithm(cfg.SigningAlgorithm)
from = "from --signing-algorithm flag"

case keyHasAlgorithm:
alg = key.Algorithm()
from = fmt.Sprintf("from JWKS, key ID %s", cfg.SigningKeyID)
}

// The above switch is exhaustive, but just in case, check that the alg isn't invalid (ie. empty)
if _, ok := alg.(jwa.InvalidKeyAlgorithm); ok {
return fmt.Errorf("signing algorithm %s is not a valid signing algorithm", alg)
}

signingAlg, ok := alg.(jwa.SignatureAlgorithm)
if !ok {
return fmt.Errorf("algorithm %s (%s) cannot be used for signing/verification", alg, from)
}

err := key.Set(jwk.AlgorithmKey, signingAlg)
if err != nil {
return fmt.Errorf("setting signing algorithm on key: %v", err)
}

return nil
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

goodbye, ugly terrible function, you have served your purpose

@@ -111,7 +111,7 @@ func (s *Signature) Verify(env map[string]string, sf SignedFielder, keySet jwk.S
}

_, err = jws.Verify([]byte(s.Value),
jws.WithKeySet(keySet),
jws.WithKeySet(keySet, jws.WithRequireKid(false)),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

without this change, all keys would have to have key ids. while the keygen utility we wrote will always output keys with key ids, we don't enforce that people use our tooling, and should let users not use key ids if they don't want to.

Copy link
Contributor Author

@moskyb moskyb Oct 10, 2023

Choose a reason for hiding this comment

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

hmm, one downside of this change is that it makes the error messaging for "you don't have the right keys for verification" a bit worse. When we required key IDs, the message was something like

WARNING: Job verification failed: invalid signature: key provider 0 failed: failed to find key with key ID "my-cool-key" in key set

which tells you a fair bit about the problem.

with jws.WithRequireKid(false), the error message is:

⚠️ WARNING: Job verification failed: invalid signature: could not verify message using any of the signatures or keys

which isn't too too much worse, but it's the same as if the job couldn't be verified (ie someone did crimes on the job).

i'm in two minds as to whether we should require/not require key IDs anyway, would love to hear some thoughts on this

Copy link
Contributor

@triarius triarius Oct 10, 2023

Choose a reason for hiding this comment

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

I'm happy to require kids because:

  1. You're going to need them if you want to rotate keys and maintain your sanity
  2. Our tool keygen requires them

So if we enforce that the key always has an ID for both signing and verification, users who use the 'blessed path' aren't going to fail.

One thing we could do is generate a key id if users can't be bothered to supply one. I should have thought of that when reviewing this: #2415

If we do that, then users don't have to think about it until they need it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👀 #2422

@moskyb moskyb requested review from DrJosh9000 and triarius October 10, 2023 03:50
@moskyb moskyb force-pushed the signing-config-cleanup branch from e13cd9d to 2e2fee9 Compare October 10, 2023 04:36
@moskyb
Copy link
Contributor Author

moskyb commented Oct 10, 2023

i've just rebased away the commit that makes key IDs optional

agent/verify_job.go Outdated Show resolved Hide resolved
Copy link
Contributor

@DrJosh9000 DrJosh9000 left a comment

Choose a reason for hiding this comment

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

Awesome!

@moskyb moskyb enabled auto-merge October 10, 2023 04:45
@moskyb moskyb force-pushed the signing-config-cleanup branch 2 times, most recently from c8b5647 to 33ab6a4 Compare October 10, 2023 05:23
@moskyb moskyb force-pushed the signing-config-cleanup branch from 33ab6a4 to cb72f8e Compare October 10, 2023 05:34
@moskyb moskyb merged commit ca59e14 into main Oct 10, 2023
@moskyb moskyb deleted the signing-config-cleanup branch October 10, 2023 05:46
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.

3 participants