Skip to content

fix: persist self-signed certificate of ec-generated key providers - #52097

Closed
waterWang wants to merge 1 commit into
keycloak:mainfrom
waterWang:fix/ec-generated-certificate-persisted
Closed

waterWang wants to merge 1 commit into
keycloak:mainfrom
waterWang:fix/ec-generated-certificate-persisted

Conversation

@waterWang

Copy link
Copy Markdown
Contributor

What

Persist the self-signed X.509 certificate for ecdsa-generated (and ecdh-generated) key providers at creation time instead of generating a fresh one on every instantiation.

Why

Closes #52093

For a key provider with ecGenerateCertificate=true, GeneratedEcdsaKeyProvider.loadKey() generates the self-signed certificate on demand and only ever writes it into the in-memory ComponentModel (model.getConfig().put(...)). The component is never persisted afterwards, so:

  • every restart produces a new certificate (new serial number / validity) for the same, unchanged EC key pair;
  • in a cluster, each node independently generates its own certificate, so the x5c claim served via the JWKS endpoint depends on which node answers;
  • COMPONENT_CONFIG never contains a certificate entry.

The rsa-generated provider does not have this problem: key pair and certificate are generated together in validateConfiguration() and persisted in the same transaction.

How

  • AbstractGeneratedEcKeyProviderFactory.generateKeys() now also generates and stores the self-signed certificate (certificate config attribute) when ecGenerateCertificate=true, mirroring AbstractGeneratedRsaKeyProviderFactory.generateKeys()/generateCertificate().
  • loadKey() keeps its lazy fallback so existing components created before this fix (key pair present, certificate absent) keep working.
  • GeneratedEcdsaKeyProviderTest now asserts the certificate is persisted in the component config.

Tests

  • GeneratedEcdsaKeyProviderTest (config size 3 -> 4 when ecGenerateCertificate=true, plus CERTIFICATE_KEY persistence assertion).

…ders

The ecdsa-generated and ecdh-generated key providers only generated the
self-signed X.509 certificate lazily inside loadKey(), mutating only the
in-memory ComponentModel. The certificate was never persisted to the
component config, so every restart (or every cluster node sharing the same
database) produced a new certificate for the same key pair, with a different
serial number and validity period, and the x5c claim served via the JWKS
endpoint changed.

Generate and persist the certificate together with the key pair in
AbstractGeneratedEcKeyProviderFactory.validateConfiguration(), matching the
behaviour of the RSA-generated provider, so the certificate stays stable
across restarts and across cluster nodes.

Signed-off-by: waterWang <waterWang@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings August 26, 2026 16:11
@waterWang
waterWang requested a review from a team as a code owner August 26, 2026 16:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Persists self-signed certificates for generated EC key providers to keep JWKS certificate data stable.

Changes:

  • Generates and stores EC certificates alongside new key pairs.
  • Verifies ECDSA certificate persistence.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
AbstractGeneratedEcKeyProviderFactory.java Generates and persists EC certificates.
GeneratedEcdsaKeyProviderTest.java Asserts certificate persistence.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +116 to +119
String generateCertificate = model.get(Attributes.EC_GENERATE_CERTIFICATE_KEY);
if (generateCertificate != null && Boolean.parseBoolean(generateCertificate)) {
generateCertificate(realm, model, keyPair);
}
@mposolda

Copy link
Copy Markdown
Contributor

Closing as the PR may require tests as well and/or fix existing tests, which seems to fail. Based on previous interaction with the user, the tests are unlikely to be added so closing PR directly (@waterWang Feel free to re-open PR or open a new PR if I am wrong here and you would like to continue on the PR).

@mposolda mposolda closed this Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

EC-generated key provider's self-signed certificate is not persisted, causing a new certificate on every restart / node

4 participants