quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.56k stars 2.62k forks source link

Connecting to mssql with authentication=ActiveDirectoryPassword fails since 2.12.0.Final #34580

Closed turing85 closed 1 week ago

turing85 commented 1 year ago

Describe the bug

When connecting to an azure-deployed MS SQL and using

quarkus.datasource.jdbc.additional-jdbc-properties.authentication=ActiveDirectoryPassword

the application fails to create a connection.

Expected behavior

Application connects, and database can be used.

Actual behavior

Application fails to connect with the following exception:

...
[INFO] Running de.turing85.quarkus.with.mssql.DatabaseTest
2023-07-06 17:20:08,565 INFO  [org.jbo.threads] (main) JBoss Threads version 3.4.2.Final
2023-07-06 17:20:10,053 WARN  [io.qua.config] (main) Unrecognized configuration key "quarkus.transaction-manager.enable-recovery" was provided; it will be ignored; verify that the dependency extension for this configuration is set or that you did not make a typo
2023-07-06 17:20:10,800 INFO  [io.quarkus] (main) quarkus-with-mssql 1.0.0-SNAPSHOT on JVM (powered by Quarkus 2.12.0.Final) started in 3.116s. Listening on: http://localhost:8081
2023-07-06 17:20:10,801 INFO  [io.quarkus] (main) Profile test activated. 
2023-07-06 17:20:10,801 INFO  [io.quarkus] (main) Installed features: [agroal, cdi, jdbc-mssql, narayana-jta, resteasy-reactive, smallrye-context-propagation, vertx]
2023-07-06 17:20:16,428 ERROR [de.tur.qua.wit.mss.DatabaseTest] (main) Error: java.sql.SQLException: Acquisition timeout while waiting for new connection
    at io.agroal.pool.ConnectionPool.handlerFromSharedCache(ConnectionPool.java:320)
    at io.agroal.pool.ConnectionPool.getConnection(ConnectionPool.java:248)
    at io.agroal.pool.DataSource.getConnection(DataSource.java:86)
    at de.turing85.quarkus.with.mssql.DatabaseTest.testDatabaseConnection(DatabaseTest.java:24)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at io.quarkus.test.junit.QuarkusTestExtension.runExtensionMethod(QuarkusTestExtension.java:1083)
    at io.quarkus.test.junit.QuarkusTestExtension.interceptTestMethod(QuarkusTestExtension.java:902)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
    at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
    at org.apache.maven.surefire.junitplatform.LazyLauncher.execute(LazyLauncher.java:56)
    at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:184)
    at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:148)
    at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:122)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
    at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
    at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)
Caused by: java.util.concurrent.TimeoutException
    at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:204)
    at io.agroal.pool.ConnectionPool.handlerFromSharedCache(ConnectionPool.java:296)
    ... 76 more

[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 12.72 s <<< FAILURE! -- in de.turing85.quarkus.with.mssql.DatabaseTest
[ERROR] de.turing85.quarkus.with.mssql.DatabaseTest.testDatabaseConnection -- Time elapsed: 5.614 s <<< ERROR!
java.lang.RuntimeException: java.sql.SQLException: Acquisition timeout while waiting for new connection
    at de.turing85.quarkus.with.mssql.DatabaseTest.testDatabaseConnection(DatabaseTest.java:35)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at io.quarkus.test.junit.QuarkusTestExtension.runExtensionMethod(QuarkusTestExtension.java:1083)
    at io.quarkus.test.junit.QuarkusTestExtension.interceptTestMethod(QuarkusTestExtension.java:902)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
    at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
    at org.apache.maven.surefire.junitplatform.LazyLauncher.execute(LazyLauncher.java:56)
    at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:184)
    at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:148)
    at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:122)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
    at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
    at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)
    Suppressed: java.sql.SQLException: Acquisition timeout while waiting for new connection
        at io.agroal.pool.ConnectionPool.handlerFromSharedCache(ConnectionPool.java:320)
        at io.agroal.pool.ConnectionPool.getConnection(ConnectionPool.java:248)
        at io.agroal.pool.DataSource.getConnection(DataSource.java:86)
        at de.turing85.quarkus.with.mssql.DatabaseTest.testDatabaseConnection(DatabaseTest.java:24)
        ... 73 more
    Caused by: java.util.concurrent.TimeoutException
        at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:204)
        at io.agroal.pool.ConnectionPool.handlerFromSharedCache(ConnectionPool.java:296)
        ... 76 more
Caused by: [CIRCULAR REFERENCE: java.sql.SQLException: Acquisition timeout while waiting for new connection]
...

How to Reproduce?

Process finished with exit code 0



### Output of `uname -a` or `ver`

_No response_

### Output of `java -version`

openjdk 17.0.1 2021-10-19 OpenJDK Runtime Environment Temurin-17.0.1+12 (build 17.0.1+12) OpenJDK 64-Bit Server VM Temurin-17.0.1+12 (build 17.0.1+12, mixed mode, sharing)

### GraalVM version (if different from Java)

N/A

### Quarkus version or git rev

2.12.0.Final

### Build tool (ie. output of `mvnw --version` or `gradlew --version`)

Apache Maven 3.9.2 (c9616018c7a021c1c39be70fb2843d6f5f9b8a1c)

### Additional information

- The last known "good" version is `2.12.0.CR1`; the first version failing the test is `2.12.0.Final`
- The current `2.x` release (`2.16.8.Final`) has the same issue
- The current `3.x` release (`3.2.0.Final`) has the issue as well
quarkus-bot[bot] commented 1 year ago

/cc @DavideD (hibernate-reactive), @Sanne (hibernate-orm,hibernate-reactive), @gavinking (hibernate-reactive), @gsmet (hibernate-orm), @mswatosh (db2), @yrodiere (hibernate-orm)

cquoss commented 1 year ago

The root cause here is that the setup is missing the msal4j dependency.

But this root cause never pops up since the time-out occurs here: https://github.com/agroal/agroal/blob/2a95e5bef7948635da4a2d0f88a53d5202868d9a/agroal-pool/src/main/java/io/agroal/pool/ConnectionPool.java#L279

I actually do not know how to fix this but dealing with it is a PITA. Whenever you observe this one has to drill down into the callable extracting the root cause.

Maybe s/o with better knowledge of this code can come up with s/th helpful here.

cquoss commented 1 year ago

What's also annoying here is the fact that one has to add all the extra deps here (json-smart, gson, jwt, msal4j). One would expect that quarkus-jdbc-mssql carries them along.

bertcarels commented 1 year ago

experienced this issue as well tried to configure mssql managed identity authentication for keycloak

I have made it work by adding the following dependencies in keycloak and doing a rebuild

 <dependency>
     <groupId>com.microsoft.azure</groupId> 
     <artifactId>msal4j</artifactId> 
     <version>1.13.3</version> 
</dependency>

<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-identity</artifactId>
    <version>1.7.0</version>
</dependency>

I tested it on Azure AKS and can confirm that both authentication with a) service principal b) managed identity are working

but I believe these dependencies need to be added on the quarkus jdbc mssql extension here: https://github.com/quarkusio/quarkus/blob/main/extensions/jdbc/jdbc-mssql/runtime/pom.xml

How could that be done? How do I propose that? Anyone can clarify? dependencies are documented here by Microsoft: https://learn.microsoft.com/en-us/sql/connect/jdbc/connecting-using-azure-active-directory-authentication?view=sql-server-ver16#client-setup-requirements

bertcarels commented 1 year ago

there's also an open issue on keycloak: https://github.com/keycloak/keycloak/issues/22830

yrodiere commented 12 months ago

But this root cause never pops up since the time-out occurs here: https://github.com/agroal/agroal/blob/2a95e5bef7948635da4a2d0f88a53d5202868d9a/agroal-pool/src/main/java/io/agroal/pool/ConnectionPool.java#L279

Hey @barreiro , it would seem that some exceptions are not propagated correctly by Agroal when using MSSQL and some optional dependencies are missing. Any idea what could be wrong exactly?

but I believe these dependencies need to be added on the quarkus jdbc mssql extension

I'm not sure they should be added to the Quarkus extension, because not all users will need them. Microsoft decided that their JDBC client should not depend on them, after all, and probably for the same reason.

We certainly could (should) document when they are needed though. Maybe here or there.

stephaneey commented 11 months ago

but I believe these dependencies need to be added on the quarkus jdbc mssql extension

I'm not sure they should be added to the Quarkus extension, because not all users will need them. Microsoft decided that their JDBC client should not depend on them, after all, and probably for the same reason.

Who don't need to leverage OAuth 2 flows nowadays? Relying on SQL authentication in 2023 isn't certainly the way to go for most organizations anymore. I think @bertcarels 'suggestion makes sense.

yrodiere commented 11 months ago

I think @bertcarels 'suggestion makes sense.

It certainly does, in his (and your) context.

In the context of people who don't need these features, the additional dependencies would represent a higher attack surface when it comes to security vulnerabilities, not to mention unwanted bloat.

It's a matter of finding the right balance between bloat and good out-of-the-box experience, for most users in most contexts.

Who don't need to leverage OAuth 2 flows nowadays?

I wouldn't know, as I don't personally use SQL Server in production environments. Microsoft obviously thinks some people don't need to leverage OAuth 2 flows, otherwise the feature would be built-in instead of requiring additional dependencies. I tend to trust Microsoft on that.

Regardless, the most pressing issue IMO is the fact that some errors get swallowed, making this issue a nightmare to debug. I hope @barreiro will be able to help on that front, and fix this in the next micro.

In the next minor, if someone more versed than I am in authentication practices (@maxandersen ? @geoand ? @gastaldi ?) decides we need out-of-the-box support for ActiveDirectory authentication with SQL Server, then sure let's go for more dependencies.

geoand commented 11 months ago

In the next minor, if someone more versed than I am in authentication practices (@maxandersen ? @geoand ? @gastaldi ?) decides we need out-of-the-box support for ActiveDirectory authentication with SQL Server, then sure let's go for more dependencies.

I'm not particularly well versed in auth practices, but OOTB support for AD at the expense of increased bloat, complexity etc is a -1 for me.

Having some kind optional support would be fine

Sanne commented 11 months ago

The Microsoft JDBC driver has a very deep dependency tree: it's not reasonable to pull in all the optional dependencies it presents, for example some of their dependency are highly contextual (e.g. only useful on certain old versions of Windows server) and last time I checked wouldn't work with native-image.

Also, it does not clearly define what is optional, this requires some domain knowledge

Admittedly this was the situation some years ago when I first looked into adding mssql support in Quarkus; perhaps things are improved by now: I'm just commenting here so that if anyone here wants to volunteer to try again and refine these choices, you know what to be careful with. I certainly did make some choices at the time, to make it work, and some might not be optimal today.

stephaneey commented 11 months ago

I understand the rationale and it is true that OAuth was not yet so dominant years ago, but nowadays, in Azure for instance, everything is 100% OIDC, and federated identities become mainstream, here again, relying on OIDC.

if anyone here wants to volunteer to try again and refine these choices, you know what to be careful with. I certainly did make some choices at the time, to make it work, and some might not be optimal today.

@bertcarels :)?

maxandersen commented 1 week ago

closing this as duplicate of https://github.com/quarkusio/quarkus/issues/36587