fix(x509): support ed25519 private keys in the x509 signer - #1868
fix(x509): support ed25519 private keys in the x509 signer#1868pujitha24 wants to merge 2 commits into
Conversation
Motivation: docs/signing.md documents that the x509 signer's `x509.pem` secret may hold a key "of type `ed25519` or `ecdsa`", but `x509Signer()` only ever handled `*ecdsa.PrivateKey`. Any other PKCS8 key type, including ed25519, was rejected with "unsupported private key type ..., only ECDSA keys are supported". A prior fix already turned the original unchecked type assertion (which used to panic the controller on an ed25519 key) into this graceful error, but ed25519 keys still could not actually be used to sign, even though the docs say they should work. The test suite already had a `TestSigner_SignED25519` test skipped with "skip test until ed25519 signing is implemented", confirming this was the known follow-up. Approach: Replace the single `pk.(*ecdsa.PrivateKey)` type assertion in x509Signer() with a type switch that also handles `ed25519.PrivateKey` via `signature.LoadED25519SignerVerifier`, from the sigstore signature package already used elsewhere in this file. Any other key type still falls through to the existing descriptive error, updated to mention both supported types. This is scoped to the x509.pem load path only; the cosign.key path already supports ed25519 via cosign's own key loader. Un-skipped TestSigner_SignED25519, which signs a payload with an ed25519 key and verifies it with ed25519.Verify. Switched TestNewSignerUnsupportedX509KeyType from an ed25519 key to a freshly generated RSA key, since ed25519 is no longer an unsupported type. Validation: - go build ./... - go test ./pkg/chains/signing/x509/... -v : all tests pass, including the newly un-skipped TestSigner_SignED25519. - go test ./pkg/chains/... : all pass. - make golangci-lint PKG=./pkg/chains/signing/x509/... : 0 issues. - Confirmed this is a real regression test: with only x509.go reverted (test left un-skipped), TestSigner_SignED25519 fails with "unsupported private key type ed25519.PrivateKey, only ECDSA keys are supported"; with the fix applied it passes. Report: tektoncd#1189 Signed-off-by: Pujitha Paladugu <10557236+pujitha24@users.noreply.github.com>
|
@pujitha24 Thank you for this. Could you verify with |
|
Fair ask, but I don't have a live cluster with Fulcio/Rekor set up in my environment, so I haven't run this end-to-end with What I can say from reading the code: this diff only touches key loading in If you can point me to a cluster/kind-e2e setup to run this against, or would rather I add an ed25519 case to the existing e2e suite, happy to do either — let me know which you'd prefer. |
Summarizing below possible options: For key-based signing with transparency, by default Chains uploads to the public Rekor ( 1. Create an Ed25519 signing secret openssl genpkey -algorithm ED25519 -out ed25519.pem
kubectl create secret generic signing-secrets -n tekton-chains \
--from-file=x509.pem=ed25519.pem --dry-run=client -o yaml | kubectl apply -f -2. Enable transparency (default URL is public Rekor) kubectl patch configmap chains-config -n tekton-chains -p '{"data":{
"transparency.enabled":"true",
"artifacts.taskrun.format":"slsa/v2alpha4",
"artifacts.oci.format":"simplesigning"
}}'3. Run both cases and watch the controller log around the Rekor upload kubectl logs -n tekton-chains deploy/tekton-chains-controller -f | grep -i "rekor\|tlog\|transparency"Alternate option: the repo's |
|
Thanks for the detailed steps. Unfortunately my environment doesn't have docker/kind/kubectl/ko available, so I can't actually stand up a cluster and run either the manual walkthrough or the e2e suite myself — I'd just be guessing at the outcome, which I don't want to do. I could add an ed25519 variant to |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1868 +/- ##
==========================================
+ Coverage 61.90% 62.19% +0.29%
==========================================
Files 64 64
Lines 4071 4092 +21
==========================================
+ Hits 2520 2545 +25
+ Misses 1269 1266 -3
+ Partials 282 281 -1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
/assign @anithapriyanatarajan |
@pujitha24 We do need E2E evidence. Per the Tekton contribution standards, changes like this need to be verified end-to-end, and that bar matters especially for this PR. Once we merge this we are effectively telling users this mode is supported. If it turns out not to work as expected, for example the user reports "I signed my artifact and now I can't verify it", which is a much worse failure for users than a slower review. On the tooling: standing up a local environment is simple, and it's a one-time setup that will pay off for future contributions too. DEVELOPMENT.md walks through it, but roughly:
Happy to help if you are stuck anywhere with these steps What I am looking for on the PR before approving:
Once that's on the PR I'm happy to approve. Thank you. |
anithapriyanatarajan asked for end-to-end evidence that ed25519 x509.pem keys actually sign, upload to Rekor, and verify against a real cluster, on top of the unit tests already added in this PR. This sandbox has no docker/kind/kubectl/ko, so that manual walkthrough cannot be produced here. As a partial, honest answer to the "E2E suite passing" ask, add a taskrun-ed25519 case to TestRekor's table so the e2e job (which does run against a real cluster) exercises the new code path: generate an ed25519 key instead of ECDSA for signing-secrets, let the controller sign with it, upload to the real Rekor, and verify the signature. To let the test secret hold either key type, change secret.x509priv from the concrete *signature.ECDSASignerVerifier to the signature.SignerVerifier interface, which both ECDSASignerVerifier and ED25519SignerVerifier satisfy. Two call sites used .Public(), a method promoted from the concrete ECDSA type and not part of the interface; switched them to .PublicKey(), which is. This does not touch the already-committed x509.go change and does not run in this environment; it only adds coverage for whoever/whatever next runs the e2e suite. Signed-off-by: Pujitha Paladugu <10557236+pujitha24@users.noreply.github.com> Assisted-by: Claude Sonnet 5 (via Claude Code)
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
Since I still don't have kind/kubectl/ko in this sandbox, I can't produce the manual walkthrough or confirm the controller comes up cleanly — I don't want to fake that. What I could do is add a This is item 3 from your list (E2E suite coverage), but items 1 and 2 (controller-up confirmation, pasted signing/verification output) still need someone with cluster access — I can't produce those here. If you're able to run the e2e suite (or the manual steps you outlined) against this branch, that would close the gap; otherwise let me know if there's another way you'd like this verified. |
Changes
The x509 signer's docs (
docs/signing.md) state that the private key storedin the
x509.pemsecret may be of typeed25519orecdsa, butx509Signer()only ever handled*ecdsa.PrivateKey. Any other PKCS8 keytype — including ed25519 — was rejected with
unsupported private key type ..., only ECDSA keys are supported(this usedto be an unchecked type assertion that panicked the controller; a prior fix
turned that into a graceful error, but ed25519 keys still could not be used
to sign at all, even though the docs say they should work).
This replaces the single
pk.(*ecdsa.PrivateKey)assertion with a typeswitch that also handles
ed25519.PrivateKeyviasignature.LoadED25519SignerVerifier(from the already-vendoredgithub.com/sigstore/sigstore/pkg/signaturepackage used elsewhere in thisfile). Any other key type still falls through to the existing descriptive
error, now mentioning both supported types.
The
TestSigner_SignED25519test, previously skipped witht.Skip("skip test until ed25519 signing is implemented"), is un-skippedand now passes.
TestNewSignerUnsupportedX509KeyType(which exercises the"unsupported key type" error path) was switched from an ed25519 key to a
freshly generated RSA key, since ed25519 is no longer unsupported.
This is scoped to the
x509.pemload path only; thecosign.keypath(
cosignSigner) already supports ed25519 via cosign's own key loader and isunaffected.
Submitter Checklist
As the author of this PR, please check off the items in this checklist:
functionality, content, code)
Release Notes
AI assistance: this change was drafted with Claude Code.
Fixes #1189