Skip to content

[DB-2037] Add EKUs phase 2: dual server certificates - #5586

Open
timothycoleman wants to merge 15 commits into
masterfrom
timothycoleman/eku-phase2
Open

[DB-2037] Add EKUs phase 2: dual server certificates#5586
timothycoleman wants to merge 15 commits into
masterfrom
timothycoleman/eku-phase2

Conversation

@timothycoleman

@timothycoleman timothycoleman commented Apr 17, 2026

Copy link
Copy Markdown
Contributor

Per the EKU KDD

Refactors:

  • Refactor: User certs plugin uses the main certificate extensions rather than having its own copy
  • Refactor: Node and User CertificateAuthenticationProviders use the same method to classify incoming certificates to guarantee consistent classification
  • Refactor: startup Certificate loading helpers

Main feature:

  • Added options that exactly mirror the certificate file and store options
  • If the extra cert is specified then both certificates are loaded and validated for trust
  • If in a cluster we check the node client certificate classifies correctly on startup for easier troubleshooting
  • Send the node client cert on outbound connections
  • Certify expiry monitor monitors both certificates

Aside:

  • NodeCertificateAuthenticationProvider no longer requires the SAN to have IP or DNS name in it. The purpose of the check is now covered by checking EKUs, leaving it redundant. The IP/DNS name was only checked to be present, not that it corresponds to the source of the connection.

… the server

was originally duplicated when this plugin lived in a separate repo
- classifies inbound ceriticates into node/user/unclassified based on EKUs
- used by both certificate authentication providers to guarantee consistent classification (can't match both providers)
…icate will be used for outgoing connections to other nodes
  The node certificate authentication provider required client certificates
  to have an IP or DNS Subject Alternative Name. This was introduced before
  EKU-based classification existed, as a heuristic for "this cert belongs
  to a machine rather than a user."

  With the inbound certificate classifier now distinguishing node certs
  from user certs by their EKU profile, the SAN requirement is redundant.
  Neither the .NET SslStream framework nor KurrentDB checks SANs against
  the actual connection origin for client certificates, so the SAN check was
  purely existence-based and provided no security benefit. (TimC: this isn't just an AI guess - we really checked)

  - Remove the SAN check from NodeCertificateAuthenticationProvider
  - Remove tests that were testing SAN-specific behaviour; rename and
    tighten the remaining tests to reflect what they actually cover
    (key usages, CN matching)
  - Move the test classes into a sub-namespace to avoid name collisions

  We've kept the HasIpOrDnsSan extension method because the outgoing node cert does still require it
  and it may be helpful later during startup validation
…nodes

use the outgoing cert as the required base for user certs (so all client certs come from the same CA)
… a cluster

if we aren't part of a cluster we won't ever use it as a client cert
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Apr 22, 2026

Copy link
Copy Markdown

Deploying eventstore with  Cloudflare Pages  Cloudflare Pages

Latest commit: 7118b5a
Status: ✅  Deploy successful!
Preview URL: https://1e02ab3e.eventstore.pages.dev
Branch Preview URL: https://timothycoleman-eku-phase2.eventstore.pages.dev

View logs

@timothycoleman timothycoleman changed the title Timothycoleman/eku phase2 [DB-2037] Add EKUs phase 2: dual server certificates Apr 22, 2026
@linear

linear Bot commented Apr 22, 2026

Copy link
Copy Markdown

@timothycoleman
timothycoleman marked this pull request as ready for review April 22, 2026 08:36
@timothycoleman
timothycoleman requested review from a team as code owners April 22, 2026 08:36
Copilot AI review requested due to automatic review settings April 22, 2026 08:36
@qodo-code-review

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Add dual server certificates for EKU phase 2 with inbound classification

✨ Enhancement 🧪 Tests

Grey Divider

Walkthroughs

Description
• Implement dual certificate support for cluster communication
  - Add separate node client certificate configuration options
  - Support both file and Windows certificate store sources
  - Validate node client certificate at startup in multi-node clusters
• Refactor certificate classification to unified inbound certificate classifier
  - Replace separate IsServerCertificate/IsClientCertificate methods
  - Classify certificates as Node, User, or Unclassified based on EKU profile
  - Remove redundant SAN requirement from node certificate authentication
• Update certificate expiry monitoring to track both certificates
• Consolidate certificate loading logic with helper methods
Diagram
flowchart LR
  A["Configuration Options"] -->|Load| B["Node Certificate"]
  A -->|Load| C["Node Client Certificate"]
  B -->|Validate| D["Certificate Chain Verification"]
  C -->|Validate| D
  C -->|Classify| E["CertificateClassification"]
  E -->|Monitor| F["Certificate Expiry Monitor"]
  C -->|Use for| G["Outbound Cluster Connections"]
  B -->|Use for| H["Inbound Server Connections"]
Loading

Grey Divider

File Changes

1. src/KurrentDB.Common/Utils/CertificateClassification.cs ✨ Enhancement +13/-0

New enum for certificate profile classification

src/KurrentDB.Common/Utils/CertificateClassification.cs


2. src/KurrentDB.Common/Utils/CertificateExtensions.cs ✨ Enhancement +48/-34

Add inbound certificate classifier and SAN helper

src/KurrentDB.Common/Utils/CertificateExtensions.cs


3. src/KurrentDB.Auth.UserCertificates/UserCertificateAuthenticationProvider.cs ✨ Enhancement +3/-4

Use unified certificate classifier for user auth

src/KurrentDB.Auth.UserCertificates/UserCertificateAuthenticationProvider.cs


View more (21)
4. src/KurrentDB.Auth.UserCertificates/CertificateExtensions.cs Refactoring +0/-127

Remove duplicate certificate extension methods

src/KurrentDB.Auth.UserCertificates/CertificateExtensions.cs


5. src/KurrentDB.Auth.UserCertificates/KurrentDB.Auth.UserCertificates.csproj Dependencies +3/-0

Add reference to KurrentDB.Common project

src/KurrentDB.Auth.UserCertificates/KurrentDB.Auth.UserCertificates.csproj


6. src/KurrentDB.Auth.UserCertificates.Tests/CertificateExtensionsTests.cs 🧪 Tests +0/-112

Remove duplicate certificate extension tests

src/KurrentDB.Auth.UserCertificates.Tests/CertificateExtensionsTests.cs


7. src/KurrentDB.Core/Certificates/CertificateProvider.cs ✨ Enhancement +2/-0

Add node client certificate properties

src/KurrentDB.Core/Certificates/CertificateProvider.cs


8. src/KurrentDB.Core/Certificates/OptionsCertificateProvider.cs ✨ Enhancement +77/-24

Load and validate dual certificates with classification

src/KurrentDB.Core/Certificates/OptionsCertificateProvider.cs


9. src/KurrentDB.Core/Certificates/CertificateExpiryMonitor.cs ✨ Enhancement +19/-11

Monitor expiry of multiple certificates

src/KurrentDB.Core/Certificates/CertificateExpiryMonitor.cs


10. src/KurrentDB.Core/Configuration/ClusterVNodeOptions.cs ⚙️ Configuration changes +51/-0

Add node client certificate configuration options

src/KurrentDB.Core/Configuration/ClusterVNodeOptions.cs


11. src/KurrentDB.Core/Configuration/ClusterVNodeOptionsExtensions.cs Refactoring +120/-40

Refactor certificate loading with helper methods

src/KurrentDB.Core/Configuration/ClusterVNodeOptionsExtensions.cs


12. src/KurrentDB.Core/Services/Transport/Http/Authentication/NodeCertificateAuthenticationProvider.cs ✨ Enhancement +30/-34

Use certificate classifier and remove SAN requirement

src/KurrentDB.Core/Services/Transport/Http/Authentication/NodeCertificateAuthenticationProvider.cs


13. src/KurrentDB.Core/ClusterVNode.cs ✨ Enhancement +17/-7

Wire up node client certificate selectors

src/KurrentDB.Core/ClusterVNode.cs


14. src/KurrentDB.Core.Tests/Certificates/CertificateExpiryMonitorTests.cs 🧪 Tests +5/-5

Update tests for multi-certificate monitoring

src/KurrentDB.Core.Tests/Certificates/CertificateExpiryMonitorTests.cs


15. src/KurrentDB.Core.Tests/Certificates/key_usages.cs 🧪 Tests +0/-116

Remove duplicate key usage tests

src/KurrentDB.Core.Tests/Certificates/key_usages.cs


16. src/KurrentDB.Core.Tests/Certificates/subject_alternative_names.cs 🧪 Tests +26/-0

Add tests for HasIpOrDnsSan helper method

src/KurrentDB.Core.Tests/Certificates/subject_alternative_names.cs


17. src/KurrentDB.Core.Tests/Services/Transport/Http/Authentication/node_certificate_authentication_provider.cs 🧪 Tests +7/-159

Refactor tests to remove SAN-specific test cases

src/KurrentDB.Core.Tests/Services/Transport/Http/Authentication/node_certificate_authentication_provider.cs


18. src/KurrentDB.Core.Tests/Services/Transport/Http/Authentication/unix_socket_authentication_provider.cs 🧪 Tests +1/-1

Move test class to sub-namespace

src/KurrentDB.Core.Tests/Services/Transport/Http/Authentication/unix_socket_authentication_provider.cs


19. src/KurrentDB.Core.XUnit.Tests/Certificates/inbound_certificate_classification.cs 🧪 Tests +72/-0

New tests for inbound certificate classification

src/KurrentDB.Core.XUnit.Tests/Certificates/inbound_certificate_classification.cs


20. src/KurrentDB.Core.XUnit.Tests/Certificates/OptionsCertificateProviderTests.cs 🧪 Tests +192/-0

New tests for dual certificate loading and validation

src/KurrentDB.Core.XUnit.Tests/Certificates/OptionsCertificateProviderTests.cs


21. docs/server/quick-start/whatsnew.md 📝 Documentation +14/-0

Document dual certificate support feature

docs/server/quick-start/whatsnew.md


22. docs/server/security/protocol-security.md 📝 Documentation +92/-0

Add node client certificate configuration documentation

docs/server/security/protocol-security.md


23. docs/server/security/user-authentication.md 📝 Documentation +2/-2

Update user cert requirements for node client cert

docs/server/security/user-authentication.md


24. docs/server/release-schedule/release-notes.md 📝 Documentation +3/-7

Update release notes for version 26.1

docs/server/release-schedule/release-notes.md


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Node-client roots ignored🐞 Bug ≡ Correctness
Description
Node client trusted roots loaded via NodeClientTrustedRootCertificate* are only used for one-time
startup verification and are never persisted/selected for runtime certificate-chain validation,
which always uses TrustedRootCerts loaded from the main trusted-root options. In dual-cert
deployments where the node client certificate chains to a different CA than the main node
certificate, inter-node mTLS (and user-certificate root matching) can fail at runtime despite
passing startup verification.
Code

src/KurrentDB.Core/Certificates/OptionsCertificateProvider.cs[R86-119]

+		if (hasNodeClientCert) {
+			var nodeClientTrustedRootCerts = options.LoadNodeClientTrustedRootCertificates();
+
+			foreach (var trustedRootCert in nodeClientTrustedRootCerts) {
+				Log.Information("Loading trusted root for node client certificate. Subject: {subject}, Thumbprint: {thumbprint}", trustedRootCert.SubjectName.Name, trustedRootCert.Thumbprint);
+			}
+
+			if (!VerifyCertificates("node client", nodeClientCertificate, nodeClientIntermediates, nodeClientTrustedRootCerts)) {
+				return LoadCertificateResult.VerificationFailed;
+			}
+		}
+
+		// Check our client certificate will be classified correctly by other nodes
+		if (options.Cluster.ClusterSize > 1 && nodeClientCertificate.ClassifyInboundCertificate(
+				disableClientAuthEkuValidation: options.Certificate.DisableClientAuthEkuValidation,
+				out var nodeClientCertDescription) is not CertificateClassification.Node) {
+
+			Log.Error(hasNodeClientCert
+				? "The node client certificate was not recognized as a node certificate: {description}"
+				: "The node certificate was not recognized as a node certificate: {description}",
+				nodeClientCertDescription);
+			return LoadCertificateResult.VerificationFailed;
+		}
+	
		// no need for a lock here since reference assignment is atomic. however, other threads may not immediately
		// see the changes and the order in which they see the changes is also not guaranteed as we don't have any
		// memory barriers here. this is not a problem as in the worst case, it will cause the certificate verifications
		// to fail when establishing/receiving a connection and the next connection retries will succeed.
		Certificate = certificate;
		IntermediateCerts = intermediates;
+		NodeClientCertificate = nodeClientCertificate;
+		NodeClientIntermediateCerts = nodeClientIntermediates;
		TrustedRootCerts = trustedRootCerts;
		_cachedReservedNodeCN = reservedNodeCN;
Evidence
OptionsCertificateProvider loads node-client trusted roots and verifies the node-client cert against
them, but then stores only the main trusted-root collection into
CertificateProvider.TrustedRootCerts (there is no separate field for node-client roots).
ClusterVNode’s TLS client-certificate validation and the DI tuple used by the user-certificate
plugin both pull roots exclusively from TrustedRootCerts, and the chain builder uses CustomRootTrust
(so missing roots are not recovered from the OS store).

src/KurrentDB.Core/Certificates/OptionsCertificateProvider.cs[74-119]
src/KurrentDB.Core/Certificates/CertificateProvider.cs[8-15]
src/KurrentDB.Core/ClusterVNode.cs[515-529]
src/KurrentDB.Core/ClusterVNode.cs[1620-1625]
src/KurrentDB.Core/Certificates/CertificateUtils.cs[247-262]
src/KurrentDB.Auth.UserCertificates/UserCertificateAuthenticationProvider.cs[127-136]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`NodeClientTrustedRootCertificate*` options are only used to verify the local node-client certificate during `LoadCertificates()`. The resulting trusted roots are not persisted, and runtime TLS validation (and user-cert root matching) continues to use only the main `TrustedRootCerts`.

### Issue Context
- Runtime certificate chain validation uses `X509ChainTrustMode.CustomRootTrust`, so the set of roots provided by the application is authoritative.
- In dual-cert mode, the node client certificate may be issued by a different CA than the node server certificate; if so, node-client-specific root settings must be used when validating inbound node client certificates.

### Fix Focus Areas
- Persist node-client trusted roots (either as a dedicated `NodeClientTrustedRootCerts` on `CertificateProvider`, or by merging node-client roots into `TrustedRootCerts` with clear semantics):
 - src/KurrentDB.Core/Certificates/CertificateProvider.cs[8-15]
 - src/KurrentDB.Core/Certificates/OptionsCertificateProvider.cs[74-119]
- Use the node-client trusted-root set for inbound *client certificate* validation (and keep server-certificate validation using the node/server root set as appropriate):
 - src/KurrentDB.Core/ClusterVNode.cs[515-529]
- Ensure the DI tuple used by the UserCertificates plugin receives the correct root set for the node-client certificate it is paired with:
 - src/KurrentDB.Core/ClusterVNode.cs[1620-1625]

### Acceptance criteria
- When `NodeClientTrustedRootCertificate*` is configured to a different CA than the main trusted roots, node-to-node connections succeed (inbound client cert validation trusts the node-client CA).
- User-certificate root matching works when user certs share a root with the node client cert, even if that root is not present in the main trusted roots.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds “dual server certificates” support by introducing a dedicated node client certificate (for outbound intra-cluster connections) alongside the existing node/server certificate, and refactors certificate classification/validation to be shared and consistent across node + user auth paths.

Changes:

  • Introduces node-client certificate configuration (file/store + trusted roots) and loads/validates node + node-client certificates at startup.
  • Centralizes inbound certificate classification into CertificateExtensions.ClassifyInboundCertificate(...) and updates node/user auth providers to use it.
  • Updates cluster networking to send the node-client certificate on outbound connections and updates certificate expiry monitoring to handle multiple certs.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/KurrentDB.Core/Services/Transport/Http/Authentication/NodeCertificateAuthenticationProvider.cs Switches node-auth logic to EKU-based inbound certificate classification.
src/KurrentDB.Core/Configuration/ClusterVNodeOptionsExtensions.cs Refactors certificate loading helpers; adds node-client cert loader + node-client trusted roots loader.
src/KurrentDB.Core/Configuration/ClusterVNodeOptions.cs Adds node-client certificate option groups (file/store + node-client trusted root store options).
src/KurrentDB.Core/ClusterVNode.cs Routes outbound node traffic to use node-client certificate; updates injected certificate tuple; updates expiry monitor wiring.
src/KurrentDB.Core/Certificates/OptionsCertificateProvider.cs Loads node + node-client certs; validates chains; startup classification check for node-client cert.
src/KurrentDB.Core/Certificates/CertificateProvider.cs Stores node-client certificate + intermediates on the provider.
src/KurrentDB.Core/Certificates/CertificateExpiryMonitor.cs Monitors multiple certificates and de-duplicates by thumbprint.
src/KurrentDB.Core.XUnit.Tests/Certificates/inbound_certificate_classification.cs Adds xUnit coverage for new inbound classification rules.
src/KurrentDB.Core.XUnit.Tests/Certificates/OptionsCertificateProviderTests.cs Adds xUnit coverage for single/dual cert loading + reserved CN behavior.
src/KurrentDB.Core.Tests/Services/Transport/Http/Authentication/unix_socket_authentication_provider.cs Renames namespace for unix socket auth provider tests.
src/KurrentDB.Core.Tests/Services/Transport/Http/Authentication/node_certificate_authentication_provider.cs Updates tests to reflect classification changes; removes SAN-based cases.
src/KurrentDB.Core.Tests/Certificates/subject_alternative_names.cs Adds tests for new HasIpOrDnsSan() helper.
src/KurrentDB.Core.Tests/Certificates/key_usages.cs Removes old NUnit key-usage tests (replaced by new xUnit tests).
src/KurrentDB.Core.Tests/Certificates/CertificateExpiryMonitorTests.cs Updates constructor usage + assertion for new expiry log format.
src/KurrentDB.Common/Utils/CertificateExtensions.cs Adds HasIpOrDnsSan() and new ClassifyInboundCertificate(...); adjusts SAN parsing to return empty on crypto error.
src/KurrentDB.Common/Utils/CertificateClassification.cs Adds new enum to represent inbound certificate classification.
src/KurrentDB.Auth.UserCertificates/UserCertificateAuthenticationProvider.cs Reuses common inbound classification logic (removes plugin-local EKU checks).
src/KurrentDB.Auth.UserCertificates/KurrentDB.Auth.UserCertificates.csproj References KurrentDB.Common to access shared certificate utilities.
src/KurrentDB.Auth.UserCertificates/CertificateExtensions.cs Removes duplicated certificate extension logic from the plugin.
src/KurrentDB.Auth.UserCertificates.Tests/CertificateExtensionsTests.cs Removes tests for removed plugin-local certificate extension logic.
docs/server/security/user-authentication.md Updates user-cert requirements to reference node client certificate.
docs/server/security/protocol-security.md Documents node-client certificate configuration options.
docs/server/release-schedule/release-notes.md Updates release notes header/version/date for 26.1 series.
docs/server/quick-start/whatsnew.md Adds “Dual certificate support for cluster communication” entry.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 527 to 529
_internalServerCertificateValidator = (cert, chain, errors, otherNames) => ValidateServerCertificate(cert, chain, errors, _intermediateCertsSelector, _trustedRootCertsSelector, otherNames);
_internalClientCertificateValidator = (cert, chain, errors) => ValidateClientCertificate(cert, chain, errors, _intermediateCertsSelector, _trustedRootCertsSelector);
_internalClientCertificateValidator = (cert, chain, errors) => ValidateClientCertificate(cert, chain, errors, _nodeClientIntermediateCertsSelector, _trustedRootCertsSelector);
_externalServerCertificateValidator = (cert, chain, errors, otherNames) => ValidateServerCertificate(cert, chain, errors, _intermediateCertsSelector, _trustedRootCertsSelector, otherNames);

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

_internalClientCertificateValidator still uses _trustedRootCertsSelector (roots for the main/node server certificate). In dual-cert setups where the node-client certificate chains to a different CA than the node server cert, inbound intra-cluster connections will fail client-certificate validation. Consider storing/selecting a separate node-client trusted-root collection (e.g., from LoadNodeClientTrustedRootCertificates) and using it for internal client-certificate validation.

Copilot uses AI. Check for mistakes.
Comment on lines +85 to +96
// Validate the node client certificate
if (hasNodeClientCert) {
var nodeClientTrustedRootCerts = options.LoadNodeClientTrustedRootCertificates();

foreach (var trustedRootCert in nodeClientTrustedRootCerts) {
Log.Information("Loading trusted root for node client certificate. Subject: {subject}, Thumbprint: {thumbprint}", trustedRootCert.SubjectName.Name, trustedRootCert.Thumbprint);
}

if (!VerifyCertificates("node client", nodeClientCertificate, nodeClientIntermediates, nodeClientTrustedRootCerts)) {
return LoadCertificateResult.VerificationFailed;
}
}

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

TryLoadNodeClientCertificate() supports node-client-specific trusted roots, but LoadCertificates() doesn't persist nodeClientTrustedRootCerts anywhere (only TrustedRootCerts is stored). This makes it difficult for the rest of the node to validate inbound node-client certs or user certs against the correct trust roots when dual-cert mode uses a different CA. Consider adding a NodeClientTrustedRootCerts field to CertificateProvider and assigning it here.

Copilot uses AI. Check for mistakes.
public X509Certificate2 Certificate;
public X509Certificate2Collection IntermediateCerts;
public X509Certificate2 NodeClientCertificate;
public X509Certificate2Collection NodeClientIntermediateCerts;

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

CertificateProvider exposes NodeClientCertificate/NodeClientIntermediateCerts but does not expose a node-client trusted-root collection. If node-client-specific trusted roots are configurable, the provider likely needs to surface them so validators can build chains for inbound intra-cluster client certificates and for user-cert auth consistently.

Suggested change
public X509Certificate2Collection NodeClientIntermediateCerts;
public X509Certificate2Collection NodeClientIntermediateCerts;
public X509Certificate2Collection NodeClientTrustedRootCerts;

Copilot uses AI. Check for mistakes.
Comment thread src/KurrentDB.Core/ClusterVNode.cs Outdated
Comment on lines +1620 to +1625
.AddSingleton<Func<(X509Certificate2 Node, X509Certificate2Collection Intermediates,
X509Certificate2Collection Roots)>>
(() => (_certificateSelector(), _intermediateCertsSelector(), _trustedRootCertsSelector()))
(() => (
_nodeClientCertificateSelector(),
_nodeClientIntermediateCertsSelector(),
_trustedRootCertsSelector()))

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

The certificate tuple injected for UserCertificateAuthenticationProvider returns the node-client cert and intermediates, but still returns _trustedRootCertsSelector() (main/node server trusted roots). If user certs are expected to chain to the node-client CA in dual-cert setups, this should likely use the node-client trusted roots (or a combined set) to avoid rejecting otherwise-valid user certificates.

Copilot uses AI. Check for mistakes.
string reservedNodeCN;
var reservedNodeCNOption = nameof(options.Certificate.CertificateReservedNodeCommonName);

// Determine the CN pattern expected from incomming node certificates.

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

Typo in comment: "incomming" should be "incoming".

Suggested change
// Determine the CN pattern expected from incomming node certificates.
// Determine the CN pattern expected from incoming node certificates.

Copilot uses AI. Check for mistakes.
Comment on lines +320 to +326
// Unclassified Cert:
error = "Certificate is not a user certificate. ";
error += hasServerAuthEku
? "Certificate has the serverAuth EKU but not the clientAuth EKU. " +
"If you are using a certificate from a public CA that does not include the clientAuth EKU, " +
"please see the documentation for the DisableClientAuthEkuValidation configuration option."
: "Certificate has the EKU extension but does not have the serverAuth EKU.";

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

The error text for unclassified certificates starts with "Certificate is not a user certificate", but this message is also surfaced when a certificate fails node classification (e.g., serverAuth-only with DisableClientAuthEkuValidation=false). Consider making the message neutral (e.g., "Certificate was not recognized as a node or user certificate") or explicitly reference the expected classification to reduce confusion in logs.

Copilot uses AI. Check for mistakes.

This is useful when you want to use a certificate from a public CA for inbound client connections (which may only have the `serverAuth` EKU), while using a certificate from a private CA with both the `serverAuth` and `clientAuth` EKUs for inter-node communication. Using dual certificates this way is an alternative to enabling [`DisableClientAuthEkuValidation`](#disable-client-authentication-eku-validation) and keeps the node in compliance with RFC 5280.

If no node client certificate is configured, the node will use its main certificate as it's client certificate.

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

Grammar: "as it's client certificate" should be "as its client certificate".

Suggested change
If no node client certificate is configured, the node will use its main certificate as it's client certificate.
If no node client certificate is configured, the node will use its main certificate as its client certificate.

Copilot uses AI. Check for mistakes.
# Release notes

This page contains the release notes for KurrentDB v26.0.
This page contains the release notes for KurrentDB v26.1.

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

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

The page says it's for KurrentDB v26.1, but the first release entry is labeled/linking to 26.0.1. Please align the heading/link (26.1.x) with the stated version, or adjust the page intro if it should still be 26.0.x.

Suggested change
This page contains the release notes for KurrentDB v26.1.
This page contains the release notes for KurrentDB v26.0.

Copilot uses AI. Check for mistakes.
Comment thread src/KurrentDB.Core/Certificates/OptionsCertificateProvider.cs Outdated
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.

2 participants