[
https://issues.apache.org/jira/browse/KNOX-3519?focusedWorklogId=1048341&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1048341
]
ASF GitHub Bot logged work on KNOX-3519:
----------------------------------------
Author: ASF GitHub Bot
Created on: 20/Oct/26 02:52
Start Date: 20/Oct/26 02:52
Worklog Time Spent: 10m
Work Description: moresandeep opened a new pull request, #1459:
URL: https://github.com/apache/knox/pull/1459
[KNOX-3519](https://issues.apache.org/jira/browse/KNOX-3519) - Set the JWKS
host on the TLS socket so HTTPS endpoint identification works under BC-FIPS
## What changes were proposed in this pull request?
Under the BouncyCastle FIPS JSSE provider, fetching a JWKS over HTTPS fails
before any
certificate is examined:
```
java.security.cert.CertificateException: No hostname specified for HTTPS
endpoint ID check
at
org.bouncycastle.jsse.provider.HostnameUtil.checkHostname(HostnameUtil.java:31)
at
org.bouncycastle.jsse.provider.ProvX509TrustManager.checkEndpointID(ProvX509TrustManager.java:333)
```
JWT verification then fails and the request is rejected with 401, even when
the JWKS
endpoint's certificate is fully trusted and carries a matching SAN.
**The change.** A new `SetHostSSLSocketFactory` decorator stamps the JWKS
URL's host onto
every socket it creates, via `setHost(String)` as declared by
`org.bouncycastle.jsse.BCSSLSocket`. It is wired in at both JWKS retrieval
paths:
`DefaultTokenAuthorityService.buildJwkSource` (default truststore) and
`IssuerTrustResourceRetriever` (per-issuer CA bundle).
Notes on the implementation:
- The BC type is reached reflectively, so Knox takes no compile dependency
on the BouncyCastle
TLS provider, it is present only in FIPS deployments. Lookup walks
interfaces first,
because BC's socket implementations are package-private and the method is
only invocable
through the public `BCSSLSocket` interface.
- On sockets that do not expose `setHost` the decorator is a no-op. That is
correct for the
stock JSSE, which identifies HTTPS endpoints from the URL already, so
non-FIPS deployments
are unaffected.
- Endpoint identification is **preserved, not bypassed**. The server
certificate must still
carry a SAN matching the JWKS host.
- The retriever built for the default path reproduces Nimbus's own defaults
exactly
(connect/read 500 ms, 51200 byte limit, `disconnectAfterUse = true`), so
timeout and size
behaviour are unchanged.
## How was this patch tested?
Patch was tested locally.
Issue Time Tracking
-------------------
Worklog Id: (was: 1048341)
Remaining Estimate: 0h
Time Spent: 10m
> Set the JWKS host on the TLS socket so HTTPS endpoint identification works
> under BC-FIPS
> ----------------------------------------------------------------------------------------
>
> Key: KNOX-3519
> URL: https://issues.apache.org/jira/browse/KNOX-3519
> Project: Apache Knox
> Issue Type: Bug
> Reporter: Sandeep More
> Assignee: Sandeep More
> Priority: Major
> Time Spent: 10m
> Remaining Estimate: 0h
>
> BC-FIPS HostnameUtil.checkHostname refuses IP literals for the HTTPS
> algorithm, it matches DNS names only and never consults iPAddress SANs. So
> the cert's IP Address:10.83.6.18 SAN is irrelevant, and no truststore change
> can fix it.
> THe result is when an ip address is used for SSL handshake throwing this error
> {code:java}
> 2026-10-19 23:15:18,262 42f8a538-720e-4467-ac21-e71c95f6f9c3 ERROR
> token.state (DefaultTokenAuthorityService.java:verifyToken(371)) - Failed to
> verify token using JWKS endpoint https://10.83.6.18:6443/openid/v1/jwks,
> reason: com.nimbusds.jose.jwk.source.JWKSetRetrievalException: Couldn't
> retrieve JWK set from URL: certificate_unknown(46)
> org.apache.knox.gateway.services.security.token.TokenServiceException: Cannot
> verify token.
> at
> org.apache.knox.gateway.services.token.impl.DefaultTokenAuthorityService.verifyToken(DefaultTokenAuthorityService.java:331)
> at
> org.apache.knox.gateway.services.token.impl.DefaultTokenAuthorityService.verifyToken(DefaultTokenAuthorityService.java:365)
> at
> org.apache.knox.gateway.provider.federation.jwt.filter.AbstractJWTFilter.verifyTokenSignature(AbstractJWTFilter.java:966)
> at
> org.apache.knox.gateway.provider.federation.jwt.filter.AbstractJWTFilter.doFullTokenValidation(AbstractJWTFilter.java:765)
> at
> org.apache.knox.gateway.provider.federation.jwt.filter.AbstractJWTFilter.validateToken(AbstractJWTFilter.java:683)
> at
> org.apache.knox.gateway.provider.federation.jwt.filter.JWTFederationFilter.parseAndValidateJWT(JWTFederationFilter.java:733)
> at
> org.apache.knox.gateway.provider.federation.jwt.filter.JWTFederationFilter.parseAndValidateJWT(JWTFederationFilter.java:720)
> at
> org.apache.knox.gateway.provider.federation.jwt.filter.JWTFederationFilter.doFilter(JWTFederationFilter.java:346)
> at
> org.apache.knox.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:391)
> at
> org.apache.knox.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:305)
> at
> org.apache.knox.gateway.filter.XForwardedHeaderFilter.doFilter(XForwardedHeaderFilter.java:50)
> at
> org.apache.knox.gateway.filter.AbstractGatewayFilter.doFilter(AbstractGatewayFilter.java:59)
> at
> org.apache.knox.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:391)
> at
> org.apache.knox.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:305)
> at
> org.apache.knox.gateway.GatewayFilter.doFilter(GatewayFilter.java:191)
> at
> org.apache.knox.gateway.GatewayFilter.doFilter(GatewayFilter.java:102)
> at
> org.apache.knox.gateway.GatewayServlet.service(GatewayServlet.java:127)
> at
> org.eclipse.jetty.ee10.servlet.ServletHolder$NotAsync.service(ServletHolder.java:1387)
> at
> org.eclipse.jetty.ee10.servlet.ServletHolder.handle(ServletHolder.java:753)
> at
> org.eclipse.jetty.ee10.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1624)
> at
> org.eclipse.jetty.ee10.websocket.servlet.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:195)
> at
> org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter(FilterHolder.java:205)
> at
> org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1596)
> at
> org.eclipse.jetty.ee10.servlet.ServletHandler$MappedServlet.handle(ServletHandler.java:1557)
> at
> org.eclipse.jetty.ee10.servlet.ServletChannel.dispatch(ServletChannel.java:828)
> at
> org.eclipse.jetty.ee10.servlet.ServletChannel.handle(ServletChannel.java:438)
> at
> org.eclipse.jetty.ee10.servlet.ServletHandler.handle(ServletHandler.java:470)
> at
> org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:575)
> at
> org.eclipse.jetty.ee10.servlet.SessionHandler.handle(SessionHandler.java:717)
> at
> org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:1102)
> at
> org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:181)
> at org.eclipse.jetty.server.Handler$Wrapper.handle(Handler.java:740)
> at
> org.apache.knox.gateway.trace.TraceHandler.handle(TraceHandler.java:72)
> at org.eclipse.jetty.server.Handler$Wrapper.handle(Handler.java:740)
> at
> org.apache.knox.gateway.filter.CorrelationHandler.handle(CorrelationHandler.java:50)
> at org.eclipse.jetty.server.Handler$Wrapper.handle(Handler.java:740)
> at
> org.apache.knox.gateway.filter.PortMappingHelperHandler.handle(PortMappingHelperHandler.java:104)
> at org.eclipse.jetty.server.Server.handle(Server.java:182)
> at
> org.eclipse.jetty.server.internal.HttpChannelState$HandlerInvoker.run(HttpChannelState.java:772)
> at
> org.eclipse.jetty.server.internal.HttpConnection.onFillable(HttpConnection.java:415)
> at
> org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:323)
> at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
> at
> org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
> at
> org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:492)
> at
> org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.epcRunTask(AdaptiveExecutionStrategy.java:428)
> at
> org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:401)
> at
> org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:255)
> at
> org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.run(AdaptiveExecutionStrategy.java:204)
> at
> org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:311)
> at
> org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:981)
> at
> org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1212)
> at
> org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1166)
> at java.base/java.lang.Thread.run(Thread.java:840)
> Caused by: com.nimbusds.jose.jwk.source.JWKSetRetrievalException: Couldn't
> retrieve JWK set from URL: certificate_unknown(46)
> at
> com.nimbusds.jose.jwk.source.URLBasedJWKSetSource.getJWKSet(URLBasedJWKSetSource.java:92)
> at
> com.nimbusds.jose.jwk.source.RetryingJWKSetSource.getJWKSet(RetryingJWKSetSource.java:99)
> at
> com.nimbusds.jose.jwk.source.OutageTolerantJWKSetSource.getJWKSet(OutageTolerantJWKSetSource.java:113)
> at
> com.nimbusds.jose.jwk.source.RateLimitedJWKSetSource.getJWKSet(RateLimitedJWKSetSource.java:107)
> at
> com.nimbusds.jose.jwk.source.CachingJWKSetSource.loadJWKSetNotThreadSafe(CachingJWKSetSource.java:330)
> at
> com.nimbusds.jose.jwk.source.RefreshAheadCachingJWKSetSource.loadJWKSetNotThreadSafe(RefreshAheadCachingJWKSetSource.java:347)
> at
> com.nimbusds.jose.jwk.source.CachingJWKSetSource.loadJWKSetBlocking(CachingJWKSetSource.java:240)
> at
> com.nimbusds.jose.jwk.source.RefreshAheadCachingJWKSetSource.getJWKSet(RefreshAheadCachingJWKSetSource.java:326)
> at
> com.nimbusds.jose.jwk.source.JWKSetBasedJWKSource.get(JWKSetBasedJWKSource.java:76)
> at
> com.nimbusds.jose.proc.JWSVerificationKeySelector.selectJWSKeys(JWSVerificationKeySelector.java:150)
> at
> com.nimbusds.jwt.proc.DefaultJWTProcessor.selectKeys(DefaultJWTProcessor.java:320)
> at
> com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:391)
> at
> com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:340)
> at
> com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:331)
> at
> org.apache.knox.gateway.services.token.impl.DefaultTokenAuthorityService.verifyToken(DefaultTokenAuthorityService.java:319)
> ... 52 more
> Caused by: org.bouncycastle.tls.TlsFatalAlert: certificate_unknown(46)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.jsse.provider.ProvSSLSocketDirect.checkServerTrusted(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.jsse.provider.ProvTlsClient$1.notifyServerCertificate(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.tls.TlsUtils.processServerCertificate(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.tls.TlsClientProtocol.handleServerCertificate(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.tls.TlsClientProtocol.receive13ServerCertificate(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.tls.TlsClientProtocol.handle13HandshakeMessage(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.tls.TlsClientProtocol.handleHandshakeMessage(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.jsse.provider.ProvTlsClientProtocol.handleHandshakeMessage(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.tls.TlsProtocol.processHandshakeQueue(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.tls.TlsProtocol.processRecord(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.tls.RecordStream.readRecord(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.tls.TlsProtocol.safeReadRecord(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.tls.TlsProtocol.blockForHandshake(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.tls.TlsClientProtocol.connect(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.jsse.provider.ProvSSLSocketDirect.startHandshake(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.jsse.provider.ProvSSLSocketDirect.startHandshake(Unknown
> Source)
> at
> java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:596)
> at
> java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:190)
> at
> java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1719)
> at
> java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1644)
> at
> java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:224)
> at
> com.nimbusds.jose.util.DefaultResourceRetriever.getInputStream(DefaultResourceRetriever.java:366)
> at
> com.nimbusds.jose.util.DefaultResourceRetriever.retrieveResource(DefaultResourceRetriever.java:269)
> at
> com.nimbusds.jose.jwk.source.URLBasedJWKSetSource.getJWKSet(URLBasedJWKSetSource.java:90)
> ... 66 more
> Caused by: java.security.cert.CertificateException: No hostname specified for
> HTTPS endpoint ID check
> at
> org.bouncycastle.fips.tls/org.bouncycastle.jsse.provider.HostnameUtil.checkHostname(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.jsse.provider.ProvX509TrustManager.checkEndpointID(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.jsse.provider.ProvX509TrustManager.checkEndpointID(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.jsse.provider.ProvX509TrustManager.checkExtendedTrust(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.jsse.provider.ProvX509TrustManager.checkTrusted(Unknown
> Source)
> at
> org.bouncycastle.fips.tls/org.bouncycastle.jsse.provider.ProvX509TrustManager.checkServerTrusted(Unknown
> Source)
> ... 90 more {code}
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)