fix: use crypto/rand instead of math/rand for ECDSA key generation#400
fix: use crypto/rand instead of math/rand for ECDSA key generation#400raballew wants to merge 1 commit intojumpstarter-dev:mainfrom
Conversation
The OIDC signing key was derived from math/rand seeded with a SHA-256 hash of an environment variable, making it cryptographically insecure and deterministic. Replaced with crypto/rand.Reader via ecdsa.GenerateKey for proper cryptographic randomness. Also removes the unused filippo.io/keygen dependency. Closes jumpstarter-dev#350 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
❌ Deploy Preview for jumpstarter-docs failed. Why did it fail? →
|
📝 WalkthroughWalkthroughReplaced deterministic ECDSA key generation (seeded from Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsTimed out fetching pipeline failures after 30000ms Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
controller/internal/oidc/op.go (1)
47-49: Pre-existing limitation: hardcoded key ID impedes rotation.The
ID()method still returns a hardcoded"default"value. Issue#350mentions this as a concern for key rotation. Consider tracking this as a follow-up improvement.Would you like me to open an issue to track adding key ID generation for proper key rotation support?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@controller/internal/oidc/op.go` around lines 47 - 49, The Signer.ID() method currently returns a hardcoded "default" which blocks key rotation; update the ID() implementation to return a real key identifier (e.g., a stored field or derived fingerprint) by adding/using a unique kid on the Signer (e.g., Signer.kid or derive from the public key via sha256/thumbprint) and ensure any code that constructs Signer (constructor or Load/Rotate methods) sets that kid consistently so rotations update it; locate the Signer struct and ID() method in op.go and replace the literal with the chosen dynamic field or derivation, and add tests to verify ID changes when keys rotate.controller/internal/controller/suite_test.go (1)
62-62: Remove unusedCONTROLLER_KEYenvironment variable setup.Line 62 sets
CONTROLLER_KEYwhich is no longer used anywhere in the codebase. The environment variable is defined in the Kubernetes deployment spec but never actually read by application code, and the test setup is dead code.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@controller/internal/controller/suite_test.go` at line 62, Remove the dead test setup that sets CONTROLLER_KEY: delete the os.Setenv("CONTROLLER_KEY", "somekey") call in the test initialization (the unused CONTROLLER_KEY environment variable) so the test suite no longer configures an environment variable that the code never reads; ensure no other tests rely on CONTROLLER_KEY before removing and run tests to verify.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@controller/internal/controller/suite_test.go`:
- Line 62: Remove the dead test setup that sets CONTROLLER_KEY: delete the
os.Setenv("CONTROLLER_KEY", "somekey") call in the test initialization (the
unused CONTROLLER_KEY environment variable) so the test suite no longer
configures an environment variable that the code never reads; ensure no other
tests rely on CONTROLLER_KEY before removing and run tests to verify.
In `@controller/internal/oidc/op.go`:
- Around line 47-49: The Signer.ID() method currently returns a hardcoded
"default" which blocks key rotation; update the ID() implementation to return a
real key identifier (e.g., a stored field or derived fingerprint) by
adding/using a unique kid on the Signer (e.g., Signer.kid or derive from the
public key via sha256/thumbprint) and ensure any code that constructs Signer
(constructor or Load/Rotate methods) sets that kid consistently so rotations
update it; locate the Signer struct and ID() method in op.go and replace the
literal with the chosen dynamic field or derivation, and add tests to verify ID
changes when keys rotate.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 98a5697c-a070-408d-b0e2-301f60abd5c6
⛔ Files ignored due to path filters (1)
controller/go.sumis excluded by!**/*.sum
📒 Files selected for processing (8)
controller/cmd/main.gocontroller/go.modcontroller/internal/controller/client_controller_test.gocontroller/internal/controller/exporter_controller_test.gocontroller/internal/controller/lease_controller_test.gocontroller/internal/controller/suite_test.gocontroller/internal/oidc/op.gocontroller/internal/oidc/op_test.go
💤 Files with no reviewable changes (1)
- controller/go.mod
|
If you do this, then there is no way to authenticate clients again. We use a secret key, created once, for the tokens. That comes mounted as an env var to the service. If you use a random one how will you authenticate tokens when they come? |
I am probably missing something, will re-read after PTO :) |
Yes that's the case, we need a key stable across controller restarts to be able to validate previously signed jwt tokens. And the secret is generated at installation time by controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/secrets-job.yaml, not chosen by the user, thus should be secure by default. |
The OIDC signing key was derived from math/rand seeded with a SHA-256 hash of an environment variable, making it cryptographically insecure and deterministic. Replaced with crypto/rand.Reader via ecdsa.GenerateKey for proper cryptographic randomness.
Also removes the unused filippo.io/keygen dependency.
Closes #350