Open Visserr2 opened 10 months ago
When using the quarkus-reactive-mysql-client (and hibernate-reactive) and dynamic credentials with Vault it will throw an error when fetching the credentials on rule 207 in the io.quarkus.reactive.mysql.client.runtime.MySqlPoolRecord.
To solve this I created an custom VaultCredentialProvider and retrieve the credentials as a Future via a virtual thread. My code looks like this:
private Map<String, String> retrieveCredentialsByVt(CredentialsProviderConfig config){
try(var executorService = Executors.newVirtualThreadPerTaskExecutor()) {
return executorService
.submit(() -> vaultDynamicCredentialsManager.getDynamicCredentials(config.credentialsMount(), config.credentialsRequestPath(), config.credentialsRole().get())
.await()
.indefinitely())
.get();
} catch (Exception e){
throw new VaultException("Cannot retrieve Vault credentials " + e.getMessage());
}
}
Im calling this method in the getCredentials-method:
if(config.credentialsRole().isPresent()){
return retrieveCredentialsByVt(config);
}
if (config.kvPath().isPresent()) {
String password = vaultKVSecretEngine.readSecret(config.kvPath().get()).get(config.kvKey());
Map<String, String> result = new HashMap<>();
result.put(PASSWORD_PROPERTY_NAME, password);
return result;
}
This way I can use reactive-mysql-client in combination with Vault Dynamic database.
Hi,
Is it possible to use Vault dynamic credentails with reactive reactive-mysql-client (and other reactive deps) ? I use two datasource (one default and one named). If I put the db-credentials in Vault KV stores it will connect to the database but if I use dynamic credentials it will give the following error:
(vert.x-eventloop-thread-1) Uncaught exception received by Vert.x: jakarta.enterprise.inject.CreationException: Error creating synthetic bean [PjUxn1Kb-s6i5R4wH8_xdk6nbwM]: java.lang.IllegalStateException: The current thread cannot be blocked: vert.x-eventloop-thread-1 at io.vertx.mysqlclient.MySQLPool_PjUxn1Kb-s6i5R4wH8_xdk6nbwM_Synthetic_Bean.doCreate(Unknown Source) at io.vertx.mysqlclient.MySQLPool_PjUxn1Kb-s6i5R4wH8_xdk6nbwM_Synthetic_Bean.create(Unknown Source) at io.vertx.mysqlclient.MySQLPool_PjUxn1Kb-s6i5R4wH8_xdk6nbwM_Synthetic_Bean.create(Unknown Source) at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:119) at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:38) at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:35) at io.quarkus.arc.generator.Default_jakarta_enterprise_context_ApplicationScoped_ContextInstances.c54(Unknown Source) at io.quarkus.arc.generator.Default_jakarta_enterprise_context_ApplicationScoped_ContextInstances.computeIfAbsent(Unknown Source) at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:35) at io.quarkus.arc.impl.ClientProxies.getApplicationScopedDelegate(ClientProxies.java:21) at io.vertx.mysqlclient.MySQLPool_PjUxn1Kb-s6i5R4wH8_xdk6nbwM_Synthetic_ClientProxy.arc$delegate(Unknown Source) at io.vertx.mysqlclient.MySQLPool_PjUxn1Kb-s6i5R4wH8_xdk6nbwM_Synthetic_ClientProxy.query(Unknown Source) at io.quarkus.reactive.datasource.runtime.ReactiveDatasourceHealthCheck.lambda$call$1(ReactiveDatasourceHealthCheck.java:60) at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:277) at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:259) at io.vertx.core.impl.EventLoopContext.lambda$runOnContext$0(EventLoopContext.java:43) at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:173) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:166) at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:1583) Caused by: java.lang.IllegalStateException: The current thread cannot be blocked: vert.x-eventloop-thread-1 at io.smallrye.mutiny.operators.uni.UniBlockingAwait.await(UniBlockingAwait.java:30) at io.smallrye.mutiny.groups.UniAwait.atMost(UniAwait.java:65) at io.smallrye.mutiny.groups.UniAwait.indefinitely(UniAwait.java:46) at io.quarkus.vault.runtime.VaultCredentialsProvider.getCredentials(VaultCredentialsProvider.java:55) at io.quarkus.vault.runtime.VaultCredentialsProvider_ClientProxy.getCredentials(Unknown Source) at io.quarkus.reactive.mysql.client.runtime.MySQLPoolRecorder.lambda$toMySQLConnectOptions$1(MySQLPoolRecorder.java:187) at java.base/java.util.ArrayList.forEach(ArrayList.java:1596) at io.quarkus.reactive.mysql.client.runtime.MySQLPoolRecorder.toMySQLConnectOptions(MySQLPoolRecorder.java:177) at io.quarkus.reactive.mysql.client.runtime.MySQLPoolRecorder.initialize(MySQLPoolRecorder.java:96) at io.quarkus.reactive.mysql.client.runtime.MySQLPoolRecorder$2.apply(MySQLPoolRecorder.java:62) at io.quarkus.reactive.mysql.client.runtime.MySQLPoolRecorder$2.apply(MySQLPoolRecorder.java:59) at io.vertx.mysqlclient.MySQLPool_PjUxn1Kb-s6i5R4wH8_xdk6nbwM_Synthetic_Bean.createSynthetic(Unknown Source) ... 24 more
It looks like retrieving the dynamics credentials from Vault are a blocking operation. But maybe i'm doing something wrong. I use the following properties to configure dynamics credentials: quarkus.vault.credentials-provider..credentials-mount=database
quarkus.vault.credentials-provider..credentials-role=
quarkus.datasource.credentials-provider=
Does anyone recognize this problem?