Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VertxHttpClientHTTPConduit does not honor default Java truststore #1665

Open
jcjveraa opened this issue Dec 16, 2024 · 9 comments
Open

VertxHttpClientHTTPConduit does not honor default Java truststore #1665

jcjveraa opened this issue Dec 16, 2024 · 9 comments

Comments

@jcjveraa
Copy link

jcjveraa commented Dec 16, 2024

Edit by @ppalaga:

VertxHttpClientHTTPConduit does not honor the default Java trust store, typically ${JAVA_HOME}/lib/security/cacerts unless the same file is configured explicitly in application.properties. This breaks the drop-in compatibility with the old default URLConnectionHTTPConduit.

Original report by @jcjveraa :

Hi there, upgrading a quarkus microservice with this extension from 3.15 to 3.16 proves to be a bit of a challenge for me. I have read the changelogs etc. but cannot figure how to change my configuration to work again.

Issue: I'm sending my requests via a simple basic-auth over single-sided https to another server. With quarkus 3.15.1 this works fine. When trying to migrate to 3.16.4 (= cxf plugin 3.16.1) suddenly the https call seems to be downgraded to plain http, as the target server responds with a SOAP message containing an application-specific security error which occurs when sending http-requests to the https-endpoint.

The standard java cacerts include the target server's CA certificates, in other words the host on which my application runs trusts the target server's certification path, so in principle no extra trust store should be required. Nevertheless I've tried setting up a tls config with just a trust store under quarkus.tls.xxx.trust-store. (etc.), but then it seems to try to go into mutual TLS mode as then it exits with Failed to create SSL connection? Not entirely sure, the error logging is cryptic at best.

Any pointers are very welcome.

My quarkus config (in yaml-mode), working fine for 3.15:

cxf:
  client:
    xxx:
      wsdl: classpath:${quarkus.cxf.codegen.wsdl2java.xxx.includes}
      username: ${yyy.zzz.username}
      password: ${yyy.zzz.password}
      secure-wsdl-access: true
      client-endpoint-url: https://the-target.server.com/
  codegen:
    wsdl2java:
      xxx:
        includes: wsdl/xxx/xxx.wsdl
        wsdl-location: classpath:wsdl/xxx/xxx.wsdl
@jcjveraa jcjveraa changed the title 3.15 -> 3.16+ upgrade breaks 3.15 -> 3.16+ upgrade breaks single-sided https Dec 16, 2024
@ppalaga
Copy link
Contributor

ppalaga commented Dec 16, 2024

Sounds like #1646
Either upgrade to Quarkus CXF 3.17.3 (available via io.quarkus.platform:quarkus-cxf-bom:3.17.4)
Or set an explicit port in client-endpoint-url:

client-endpoint-url: https://the-target.server.com:443/

@ppalaga
Copy link
Contributor

ppalaga commented Dec 16, 2024

Feel free to reopen if you feel this is not a duplicate of #1646

@ppalaga ppalaga closed this as not planned Won't fix, can't repro, duplicate, stale Dec 16, 2024
@ppalaga ppalaga added this to the no fix/won't fix milestone Dec 16, 2024
@jcjveraa
Copy link
Author

jcjveraa commented Dec 16, 2024 via email

@jcjveraa
Copy link
Author

Hi Peter,

Unfortunately no luck for both Quarkus 3.16.4 with Quarkus CXF 3.16.1, and Quarkus 3.17.4 with Quarkus CXF 3.17.3. Adding the explicit port This gives a completely different error - now the connection to the server fails completely, instead of it receiving a 'http call to a https endpoint' message.

I've tried both the 'regular' client-endpoint-url and the url with the explicit port added in 3.17.4 and both fail in the same manner.

Note that my client-endpoint-url is https://my.company.domain/something/else (or https://my.company.domain:443/something/else) - so with a path. I've tried both with and without a trailing slash.

Reverting to the url without port (https://my.company.domain/something/else) continues to function in 3.15 and give the 'http call to a https service' application-error message on 3.16. Note that in 3.17 I never receive the application error, but only the error below.

This is the error log when running 3.17

(... pretty printed request, triggered by setting quarkus.cxf.client.xxx.logging.enabled=pretty )
  </soap:Body>
</soap:Envelope>


2024-12-17 09:22:04,575 WARN  [org.apa.cxf.pha.PhaseInterceptorChain] (executor-thread-1) Interceptor for {http://www.YYY.ZZZ.com}YYYService#{http://www.YYY.ZZZ.com}YYYOperation has thrown exception, unwinding now: org.apache.cxf.interceptor.Fault: Could not send Message.
	at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:67)
	at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
	at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:530)
	at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:441)
	at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:356)
	at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:314)
	at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
	at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:140)
	at jdk.proxy9/jdk.proxy9.$Proxy140.YYYOperation(Unknown Source)
	at my.company.MySoapClientClass.getSoapResult(MySoapClientClass.java:58)
	(... further stack trace in our application)
	
Caused by: java.io.IOException: Unable to receive HTTP response from https://my.company.domain/something/else 
	at io.quarkiverse.cxf.vertx.http.client.VertxHttpClientHTTPConduit$RequestBodyHandler$Mode$Sync.awaitResponseInternal(VertxHttpClientHTTPConduit.java:1070)
	at io.quarkiverse.cxf.vertx.http.client.VertxHttpClientHTTPConduit$RequestBodyHandler$Mode$Sync.awaitResponse(VertxHttpClientHTTPConduit.java:1046)
	at io.quarkiverse.cxf.vertx.http.client.VertxHttpClientHTTPConduit$RequestBodyHandler.handle(VertxHttpClientHTTPConduit.java:568)
	at io.quarkiverse.cxf.vertx.http.client.VertxHttpClientHTTPConduit$RequestBodyHandler.handle(VertxHttpClientHTTPConduit.java:429)
	at io.quarkiverse.cxf.vertx.http.client.VertxHttpClientHTTPConduit$RequestBodyOutputStream.close(VertxHttpClientHTTPConduit.java:424)
	at org.apache.cxf.ext.logging.LoggingOutputStream.postClose(LoggingOutputStream.java:53)
	at org.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:228)
	at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
	at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:717)
	at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:63)
	... 38 more
Caused by: io.vertx.core.http.HttpClosedException: Connection was closed
	

For completeness, here is my pom.xml showing the 'context' in which Quarkus CXF operates.

	<properties>
		<compiler-plugin.version>3.13.0</compiler-plugin.version>
		<maven.compiler.release>17</maven.compiler.release>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
		<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
		<quarkus.platform.version>3.17.4</quarkus.platform.version>
		<skipITs>true</skipITs>
		<surefire-plugin.version>3.5.2</surefire-plugin.version>
	</properties>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>${quarkus.platform.group-id}</groupId>
				<artifactId>${quarkus.platform.artifact-id}</artifactId>
				<version>${quarkus.platform.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
				<groupId>${quarkus.platform.group-id}</groupId>
				<artifactId>quarkus-cxf-bom</artifactId>
				<version>${quarkus.platform.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<dependencies>
		<dependency>
			<groupId>io.quarkiverse.cxf</groupId>
			<artifactId>quarkus-cxf</artifactId>
		</dependency>
		<dependency>
			<groupId>io.quarkus</groupId>
			<artifactId>quarkus-rest-jackson</artifactId>
		</dependency>
		<dependency>
			<groupId>io.quarkus</groupId>
			<artifactId>quarkus-arc</artifactId>
		</dependency>
		<dependency>
			<groupId>io.quarkus</groupId>
			<artifactId>quarkus-rest</artifactId>
		</dependency>
		<dependency>
			<groupId>io.quarkus</groupId>
			<artifactId>quarkus-micrometer-registry-prometheus</artifactId>
		</dependency>

		<dependency>
			<groupId>io.quarkus</groupId>
			<artifactId>quarkus-junit5</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>io.quarkus</groupId>
			<artifactId>quarkus-junit5-mockito</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>io.quarkus</groupId>
			<artifactId>quarkus-jacoco</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>io.rest-assured</groupId>
			<artifactId>rest-assured</artifactId>
			<scope>test</scope>
		</dependency>
<!-- these datatypes are just POJOs, this dependency has no further dependencies -->
		<dependency>
			<groupId>my.company.datatypes</groupId>
			<artifactId>datatypes</artifactId>
			<version>17.10.0</version>
		</dependency>
		<dependency>
			<groupId>io.quarkus</groupId>
			<artifactId>quarkus-smallrye-openapi</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.36</version>
		</dependency>

		<dependency>
			<groupId>io.quarkus</groupId>
			<artifactId>quarkus-config-yaml</artifactId>
		</dependency>
	</dependencies>

@jcjveraa
Copy link
Author

jcjveraa commented Dec 17, 2024

I think some transistive dependencies are missing, when I added the following it started working... Will raise another issue for this.

	<dependency>
		<groupId>io.quarkus</groupId>
		<artifactId>quarkus-vertx</artifactId>
	</dependency>

@ppalaga
Copy link
Contributor

ppalaga commented Dec 17, 2024

Thanks for investigating further, @jcjveraa.
Adding quarkus-vertx should not matter, because it already is a transitive of quarkus-cxf. I do not think anything changed there since 3.15. I commented on that in #1666.
If upgrade to the latest 3.17 did not solve the problem, I have two more suspects:

  1. Is perhaps your service requiring authorization retransmits - i.e. sending 401 or 407 on first request and expects some auth headers in the next exchange? - this is to do for VertxHttpClientHTTPConduit - see Support authorization retransmits in VertxHttpClientHTTPConduit #1616
  2. How do you configure the trust store of the client? Using some Java code or using Quarkus style configuration (application.yaml or system properties?)

@ppalaga
Copy link
Contributor

ppalaga commented Dec 17, 2024

If 3.15 worked for you, could you please try if forcing the old default conduit via quarkus.cxf.client."client-name".http-conduit-factory = URLConnectionHTTPConduitFactory can serve as a workaround for you?

@jcjveraa
Copy link
Author

jcjveraa commented Dec 17, 2024

Hi again, sorry for the red herring for #1666.

The 2nd item you mentioned seems to have been the culprit. Apparently configuring a trust store is not checked at startup (i.e. the app will start without it), but still mandatory. CXF doesn't throw an error when you specify a https based url without explicitly setting the trust store, but it won't work without specifying a trust store.

When explicitly configuring a tls store it works. Note: the CA's for my case are in cacerts, I appreciate that often this would not be the case, but in my organization/in the base images we use it is.

Should it not use the bundled trust store by default? With 3.15 this 'just worked' - perhaps it was using the bundled cacerts?

quarkus:
  cxf:
    client:
      xxx:
        # ... other config
        tls-configuration-name: xxx
  tls:
    xxx:
      trust-store:
        jks:
          password: changeit
          path: ${JAVA_HOME}/lib/security/cacerts

@ppalaga
Copy link
Contributor

ppalaga commented Dec 17, 2024

When explicitly configuring a tls store it works. Note: the CA's for my case are in cacerts

Oh, I see, that's a very interesting case! Let me see what can be done about it.

@ppalaga ppalaga changed the title 3.15 -> 3.16+ upgrade breaks single-sided https VertxHttpClientHTTPConduit does not honor default Java truststore Dec 17, 2024
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

No branches or pull requests

2 participants