KNOX-3359 - Support Single-Purpose EKU Certificates#1291
Conversation
Design for separate client/server keystores and truststores to support single-purpose (single-EKU) certificates, gated behind an explicit gateway.tls.single.eku.enabled toggle with fail-fast startup validation. # Conflicts: # gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/AliasBasedTokenStateServiceTest.java
…ulting to true when single-EKU is on wire gateway.httpclient.twoWaySsl.enabled into DefaultHttpClientFactory; update log message
Test Results36 tests 36 ✅ 5s ⏱️ Results for commit 6945815. ♻️ This comment has been updated with latest results. |
| public boolean isHttpClientTwoWaySslEnabled() { | ||
| String configured = get(HTTP_CLIENT_TWO_WAY_SSL_ENABLED); | ||
| if (configured != null) { | ||
| return Boolean.parseBoolean(configured); |
There was a problem hiding this comment.
I believe parseBoolean returns false for null, so I think you could eliminate the null check unless this method intends to fall back to isSingleEkuEnabled() IFF two-way SSL is NOT explicitly configured. Is that the intent here? If so, this only applies to HTTP clients employed by Knox?
There was a problem hiding this comment.
Yeah, this method intends to fall back to isSingleEkuEnabled() this is because, for single EKU feature to work two-way-ssl is required as a result if two-way-ssl is not configured we default it to isSingleEkuEnabled().
So, if someone turned on isSingleEkuEnabled() then they not need to specifically turn on two-way-ssl as those go hand in hand.
| // 1. Outbound client-identity keystore must be configured and contain the configured key entry. | ||
| String clientKeystorePath = config.getHttpClientKeystorePath(); | ||
| if (clientKeystorePath == null || clientKeystorePath.isEmpty()) { | ||
| throw new ServiceLifecycleException("Single-EKU mode is enabled (" + GatewayConfig.TLS_SINGLE_EKU_ENABLED |
There was a problem hiding this comment.
Is it not valid to have single-purpose certs enabled WITHOUT two-way SSL, thus not requiring the client identity keystore?
There was a problem hiding this comment.
single-purpose certs need to have two-way SSL, this was pointed out by @smolnar82 in his offline review
This means Knox in "single-EKU mode" will start happily with a client keystore holding a serverAuth-only or dual-purpose cert — exactly the misconfiguration this feature exists to catch. The validation gives a false sense of assurance, and the tests reflect the gap (JettySSLServiceTest covers path-missing, truststore-missing, client-auth-disabled, and cert-not-a-key, but there is no EKU test).
|
|
||
| // 2. Inbound client authentication must be enforced (server truststore + client-auth). | ||
| if (config.getTruststorePath() == null) { | ||
| throw new ServiceLifecycleException("Single-EKU mode is enabled but the server truststore (" |
There was a problem hiding this comment.
Again, is it not permissible to have single-purpose certs enabled for Knox without assuming/requireing two-way SSL?
There was a problem hiding this comment.
Correct, two-way-SSL is required for this feature. But this change specifically ensures that we have truststore configured for clients who will talk to us over mTLS.
| throw new ServiceLifecycleException("Single-EKU mode is enabled but the server truststore (" | ||
| + GatewayConfig.GATEWAY_TRUSTSTORE_PATH + ") is not configured. Server will not start."); | ||
| } | ||
| if (!config.isClientAuthNeeded() && !config.isClientAuthWanted()) { |
There was a problem hiding this comment.
Here too it seems two-way SSL is required just because single-purpose certs are enabled.
There was a problem hiding this comment.
I don't think support for single-purpose certs necessitates mTLS; I think they are orthogonal concerns, but I may be wrong.
There was a problem hiding this comment.
You might be right, let me check.
(It is very important that you created an Apache Knox JIRA for this change and that the PR title/commit message includes the Apache Knox JIRA ID!)
KNOX-3359 - Support Single-Purpose EKU Certificates
Public CAs are retiring dual purpose certificates that carry both serverAuth and clientAuth Extended Key Usages. This change allows Knox to use two separate keystores, one for its inbound TLS server identity (serverAuth only) and one for its outbound mTLS client identity (clientAuth only).
What changes were proposed in this pull request?
gateway.tls.single.eku.enabled— new toggle that activates single-EKU mode. Off by default all existing behavior is unchanged when it is off.gateway.httpclient.twoWaySsl.enabled— new global flag to activate outbound mTLS across all dispatches without requiring use-two-way-ssl="true" on every service definition. Automatically defaults to true whengateway.tls.single.eku.enabled=true, so enabling single-EKU mode is a single config change with sane defaults.Notes
Note that this feature is independent of mTLS. mTLS can be configured using the existing properties
How was this patch tested?
Unit Tests
Manual Tests
Tested the following scenarios
Happy path: clientAuth cert + basic auth → 200, backend sees knox-client
No client cert → inbound TLS handshake rejected (client.auth.needed=true)
serverAuth-ONLY cert presented as inbound client cert → rejected (EKU check)
Valid client cert but NO credentials → TLS ok, HTTP 401 from Knox'
Integration Tests
Added new integration tests
UI changes
NA