Open Ntung029 opened 2 years ago
/cc @DavideD, @Sanne, @barreiro, @gavinking, @gsmet, @mswatosh
2022-10-29 00:47:06,808 WARN [io.agr.pool] (agroal-11) Datasource '
': This driver is not configured for integrated authentication. ClientConnectionId:9ccec68f-303f-41ed-854e-db243170bf23
Hey @barreiro , this looks like an unsupported feature, maybe an incompatibility? Can you shed some light? I personally have no idea what this feature even is...
My guess is that we probably need to register something for reflection in the driver (maybe). But now what...
The MS SQL JDBC driver supports a whole host of non-standard authentication methods; among these there's integration with Kerberos, possibly needing to load native windows DDL libraries getting loaded, or integrate with the Azure cloud SDK dependencies (dozens of them).
It might well be that with some luck you just need a couple additional reflections for this particular user, but be aware of the potential pandora box.
@Ntung029 we can try helping for your specific case - could you elaborate on your security setup please? And ideally if we could reproduce it in some way, that might be essential to be able to help you.
Also - is this actually running in native-image mode? Or is it failing in JVM mode too?
In case it's JVM, you might be missing some of the optional dependencies.
Thanks everyone for your response.
The same error happens with JVM image in integrated authentication mode. The SQL server has sql encryption enforce sets to true and enables both SQL Server and Windows Authentication mode.
Do you have a document about properties in quarkus.datasource.jdbc.additional-jdbc-properties
?
`2022-11-01 18:09:08,624 INFO [io.qua.sma.ope.run.OpenApiRecorder] (main) CORS filtering is disabled and cross-origin resource sharing is allowed without restriction, which is not recommended
in production. Please configure the CORS filter through 'quarkus.http.cors.*' properties. For more information, see Quarkus HTTP CORS documentation
demo-mssql-connection-fruit-service-1 | 2022-11-01 18:09:13,656 WARN [org.hib.eng.jdb.env.int.JdbcEnvironmentInitiator] (JPA Startup Thread:
... 2022-11-01 18:09:13,923 INFO [io.quarkus] (main) demo-mssql-connection 1.0-SNAPSHOT on JVM (powered by Quarkus 2.13.3.Final) started in 6.333s. Listening on: http://0.0.0.0:8080 demo-mssql-connection-fruit-service-1
2022-11-01 18:09:37,840 WARN [io.agr.pool] (agroal-11) Datasource '
`
I believe this is how properties are specified with additional-jdbc-properties
and these should be the two needed for Integrated Authentication with SQL Server on Windows:
quarkus.datasource.jdbc.additional-jdbc-properties.authenticationScheme=JavaKerberos
quarkus.datasource.jdbc.additional-jdbc-properties.integratedSecurity=true
This is assuming you're using the Krb5LoginModule, and not the .dll option, in which case see this document for the required properties: https://learn.microsoft.com/en-us/sql/connect/jdbc/using-kerberos-integrated-authentication-to-connect-to-sql-server?view=sql-server-ver16
Hopefully those get you past the "This driver is not configured for integrated authentication" error
Thanks @mvwatosh for your suggestion. I have tried the authenticationScheme JavaKerberos and got this error in the native image.
demo-mssql-connection-fruit-service-1 | 2022-11-01 19:48:54,427 INFO [io.qua.sma.ope.run.OpenApiRecorder] (main) CORS filtering is disabled and cross-origin resource sharing is allowed without restriction, which is not recommended
in production. Please configure the CORS filter through 'quarkus.http.cors.*' properties. For more information, see Quarkus HTTP CORS documentation
demo-mssql-connection-fruit-service-1 | 2022-11-01 19:48:54,625 WARN [io.agr.pool] (agroal-11) Datasource '<default>': Failed to create connection due to ExceptionInInitializerError
demo-mssql-connection-fruit-service-1 | 2022-11-01 19:48:54,629 ERROR [io.qua.run.Application] (main) Failed to start application (with profile prod): java.lang.ClassNotFoundException: sun.security.provider.ConfigFile
demo-mssql-connection-fruit-service-1 | at java.lang.Class.forName(DynamicHub.java:1136)
demo-mssql-connection-fruit-service-1 | at javax.security.auth.login.Configuration$2.run(Configuration.java:253)
demo-mssql-connection-fruit-service-1 | at javax.security.auth.login.Configuration$2.run(Configuration.java:249)
demo-mssql-connection-fruit-service-1 | at java.security.AccessController.executePrivileged(AccessController.java:145)
demo-mssql-connection-fruit-service-1 | at java.security.AccessController.doPrivileged(AccessController.java:569)
demo-mssql-connection-fruit-service-1 | at javax.security.auth.login.Configuration.getConfiguration(Configuration.java:248)
demo-mssql-connection-fruit-service-1 | at com.microsoft.sqlserver.jdbc.KerbAuthentication.<clinit>(KerbAuthentication.java:47)
demo-mssql-connection-fruit-service-1 | at com.microsoft.sqlserver.jdbc.SQLServerConnection.logon(SQLServerConnection.java:4862)
demo-mssql-connection-fruit-service-1 | at com.microsoft.sqlserver.jdbc.SQLServerConnection$LogonCommand.doExecute(SQLServerConnection.java:4845)
demo-mssql-connection-fruit-service-1 | at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7627)
demo-mssql-connection-fruit-service-1 | at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:3912)
demo-mssql-connection-fruit-service-1 | at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:3358)
demo-mssql-connection-fruit-service-1 | at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:2950)
demo-mssql-connection-fruit-service-1 | at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:2790)
demo-mssql-connection-fruit-service-1 | at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:1663)
demo-mssql-connection-fruit-service-1 | at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:1064)
demo-mssql-connection-fruit-service-1 | at io.agroal.pool.ConnectionFactory.createConnection(ConnectionFactory.java:226)
demo-mssql-connection-fruit-service-1 | at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:535)
demo-mssql-connection-fruit-service-1 | at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:516)
demo-mssql-connection-fruit-service-1 | at java.util.concurrent.FutureTask.run(FutureTask.java:264)
demo-mssql-connection-fruit-service-1 | at io.agroal.pool.util.PriorityScheduledExecutor.beforeExecute(PriorityScheduledExecutor.java:75)
demo-mssql-connection-fruit-service-1 | at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
demo-mssql-connection-fruit-service-1 | at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
demo-mssql-connection-fruit-service-1 | at java.lang.Thread.run(Thread.java:833)
demo-mssql-connection-fruit-service-1 | at com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:705)
demo-mssql-connection-fruit-service-1 | at com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine(PosixPlatformThreads.java:202)
demo-mssql-connection-fruit-service-1 |
demo-mssql-connection-fruit-service-1 exited with code 1
That looks like it's getting farther than before, can you try it in JVM mode? sun.security.provider.ConfigFile
is a JDK class, so missing that seems likely to be caused by the native compilation.
Thanks @mswatosh for your input. I think the right way is to use JDBC with JavaKerberos authentication scheme but it needs to config the Kerberos setting for microservice and SQL service.
It turns out that the microservice does not have integrated authentication config. The current setup uses JTDS driver which can use the AD credential to log in to SQL server.
When I switch to the JTDS driver, the JVM image can login to SQL server using AD credentials. However, the quarkus-smallrye-health cannot get the data connection for the Readiness healthcheck.
apaas-apaas-service-1 | at io.smallrye.mutiny.operators.uni.UniAndCombination.subscribe(UniAndCombination.java:54)
apaas-apaas-service-1 | at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
apaas-apaas-service-1 | at io.smallrye.mutiny.operators.uni.UniBlockingAwait.await(UniBlockingAwait.java:60)
apaas-apaas-service-1 | at io.smallrye.mutiny.groups.UniAwait.atMost(UniAwait.java:65)
apaas-apaas-service-1 | at io.smallrye.health.SmallRyeHealthReporter.getHealth(SmallRyeHealthReporter.java:217)
apaas-apaas-service-1 | at io.smallrye.health.SmallRyeHealthReporter_ClientProxy.getHealth(Unknown Source)
apaas-apaas-service-1 | at io.quarkus.smallrye.health.runtime.SmallRyeHealthHandler.getHealth(SmallRyeHealthHandler.java:11)
apaas-apaas-service-1 | at io.quarkus.smallrye.health.runtime.SmallRyeHealthHandlerBase.doHandle(SmallRyeHealthHandlerBase.java:44)
apaas-apaas-service-1 | at io.quarkus.smallrye.health.runtime.SmallRyeHealthHandlerBase.handle(SmallRyeHealthHandlerBase.java:31)
apaas-apaas-service-1 | at io.quarkus.smallrye.health.runtime.SmallRyeHealthHandler.handle(SmallRyeHealthHandler.java:7)
apaas-apaas-service-1 | at io.quarkus.smallrye.health.runtime.SmallRyeHealthHandlerBase.handle(SmallRyeHealthHandlerBase.java:19)
apaas-apaas-service-1 | at io.vertx.ext.web.impl.BlockingHandlerDecorator.lambda$handle$0(BlockingHandlerDecorator.java:48)
apaas-apaas-service-1 | at io.vertx.core.impl.ContextBase.lambda$null$0(ContextBase.java:137)
apaas-apaas-service-1 | at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:264)
apaas-apaas-service-1 | at io.vertx.core.impl.ContextBase.lambda$executeBlocking$1(ContextBase.java:135)
apaas-apaas-service-1 | at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:555)
apaas-apaas-service-1 | at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
apaas-apaas-service-1 | at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
apaas-apaas-service-1 | at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
apaas-apaas-service-1 | at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
apaas-apaas-service-1 | at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
apaas-apaas-service-1 | at java.base/java.lang.Thread.run(Thread.java:829)
apaas-apaas-service-1 |
apaas-apaas-service-1 | 2022-11-07 16:53:12,618 INFO [io.sma.health] (executor-thread-0) SRHCK01001: Reporting health down status: {"status":"DOWN","checks":[{"name":"Service simple health check","status":"UP"},{"name":"io.qua
rkus.agroal.runtime.health.DataSourceHealthCheck_ClientProxy","status":"DOWN","data":{}}]}
Another issue is I cannot create the native image with JTDS driver because of the initiation of Inet4Address class in the JTDS driver.
`Caused by: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: No instances of java.net.Inet4Address are allowed in the image heap as this class should be initialized at image runtime. To see how this object got instantiated use --trace-object-instantiation=java.net.Inet4Address.
`
Using integratedSecurity=true
and authenticationScheme=JavaKerberos
should be able to pick up the AD credential off the system (it uses the default ccache on the system to look for credentials). Are you getting an error message when running in JVM mode with those properties and the SQLServer JDBC driver?
It turns out that we don't have the integrated authentication config for microservice. It is working with JTDS driver which can log in to SQL server using AD credentials by providing both username and password.
Hey everybody,
Sorry to comment on such an old issue, but I concur. MSSQL JDBC driver does not support integration authentication in native image.
It works flawlessly in JVM mode but it doesn't seem to pick up the login config file I've provided in the system property: java.security.auth.login.config.
Of course I've also set the following system properties: -Dsun.security.krb5.debug=true -Dsun.security.spnego.debug=true but there's no debugging at all, so it would appear that the driver doesn't pick up on the fact that it's suppose to use Kerberos.
I guess it could be something with registering some classes for reflection, but I've not been able to figure out which ones. I've tried to register com.sun.security.auth.module.Krb5LoginModule but that didn't do anything.
Btw, to make it run (not build) I needed to set these parameters:
quarkus.native.additional-build-args =\
-H:+UnlockExperimentalVMOptions,\
-H:ReflectionConfigurationFiles=reflection-config.json,\
-H:IncludeResourceBundles=sun.security.util.AuthResources,\
-H:-UnlockExperimentalVMOptions
and in the reflection-config.json I have:
[
{
"name" : "sun.security.provider.ConfigFile",
"allDeclaredConstructors" : true,
"allPublicConstructors" : true,
"allDeclaredMethods" : true,
"allPublicMethods" : true,
"allDeclaredFields" : true,
"allPublicFields" : true
}
]
I hope somebody can share some insights :-)
@JesperBerggren Have you managed to progress with the issue or have you workaround it somehow?
Unfortunately no. Our "workaround" is not to run in native mode.
Unfortunately no. Our "workaround" is not to run in native mode.
@JesperBerggren perhaps this will be of some use to you Okay, I have managed to overcome this. I am not sure how stable this is (yet to be checked) but.
is this more/different auth than active directory as discussed in https://github.com/quarkusio/quarkus/issues/34580 ?
Right @maxandersen , it's possibly different from #34580. From Sanne's message above:
The MS SQL JDBC driver supports a whole host of non-standard authentication methods; among these there's integration with Kerberos, possibly needing to load native windows DDL libraries getting loaded, or integrate with the Azure cloud SDK dependencies (dozens of them).
@maxandersen yes, these are different auth methods. In this thread kerberos is discussed: https://learn.microsoft.com/en-us/sql/connect/jdbc/using-kerberos-integrated-authentication-to-connect-to-sql-server?view=sql-server-ver16 vs AD Auth in the other: https://learn.microsoft.com/en-us/sql/connect/jdbc/connecting-using-azure-active-directory-authentication?view=sql-server-ver16
@sebagdev maybe we should work on having a configuration property to enable this automatically?
I'm not sure exactly which configuration triggers the authentication you are using but it seems like something we could integrate to Quarkus directly (and automatically register for reflection).
The only thing is that we need a build time property for it because reflection is handled at build time.
I think with a good name for the config property and your reflection config above, the patch is almost written.
@gsmet I think that's great idea. It would not be a hassle to use if this configuration property would be described in quarkus-jdbc-mssql or the guide.
The authentication is triggered by authenticationScheme of the jdbc connection string. My full config looks like this:
quarkus.datasource.jdbc.url = jdbc:sqlserver://${DB_HOST};databasename=${DB_NAME};integratedsecurity=true;trustServerCertificate=true;authenticationScheme=JavaKerberos;multiSubnetFailover=true;encrypt=true;userName=${DB_USERNAME};password=${DB_PASSWORD};sslProtocol=TLSv1.2
quarkus.hibernate-orm.database.generation=none
quarkus.native.resources.includes=*.properties,*.json
quarkus.native.additional-build-args =\
-H:+UnlockExperimentalVMOptions, \
-H:ReflectionConfigurationFiles=reflection-config.json, \
-H:IncludeResourceBundles=sun.security.util.AuthResources, \
-H:AdditionalSecurityProviders=sun.security.jgss.SunProvider, \
-H:+TraceSecurityServices
quarkus.naming.enable-jndi=true
The issue for this is that my code most likely will only fix Kerberos, I am not sure about other authentication schemes (AD auth variants). Also keeping this up to date might be challenging - I had an issue to properly setup locally DB with Kerberos so I ended up on verifying this on dev environment.
But in the long run.. I think it might be worth it, as it can draw to quarkus more enterprise developers who are bound to corporate policies and are hesitant or simply cannot easily run JDBC MSSQL connections.
Description
I have an issue when connecting the service to SQL DB from a native image. Because of security requirement, I need to use integrated security by specifying these additional jdbc properties bellow:
Then I start the application in the quarkus-distroless-image:1.0. The application cannot find the connection to SQL DB and the error message shows as bellow. I have verified the connection setting using SQL credentials which can connect to SQL DB. Could anyone advise the setting or driver that can support integrated authentication to SQL DB.
Implementation ideas
No response