如何使用 Panache Hibernate 更新/重新启动数据库连接

问题描述 投票:0回答:1

我的秘密存在于 AWS Secrets Manager 中。一些 quarkus API 在 ECS 集群后面运行,连接到 RDS 数据库。这些机密是在 API 应用程序的启动时(或初始化)提取的,并且 RDS 的机密每周都会轮换,这会导致运行时出现连接错误,并出现以下错误:

org.hibernate.engine.jdbc.spi.SqlExceptionHelper
FATAL: password authentication failed for user
avax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: Unable to acquire JDBC Connection

我的应用程序是用 Kotlin 编写的,使用 quarkus 作为框架,使用 Hibernate ORM with Panache 连接到 RDS。 该应用程序使用应用程序 .yml 作为配置源和自定义数据源配置类,如下所示

org.eclipse.microprofile.config.spi.ConfigSource
,它从AWS获取秘密并覆盖getValue方法并在初始化(开始时间)期间设置一些数据源配置,例如密码。该数据库是 Aurora PostgreSQL,但我想这无关紧要。

我希望应用程序在运行时能够使用正确的密码与数据库建立连接。最好仍然使用 Panache,但如果没有其他方法我可以更改数据库连接库。连接如何在运行时获得正确的凭据?如何告诉 Panache 使用一些新凭据打开新连接?

我的问题的另一个解决方案可能是重新启动 ECS 任务。但任务定义似乎记住了旧的连接凭据。我不想每周创建一个新的任务定义。如何正确重启应用程序?

我尝试添加自定义凭据提供程序(将此作为参考https://quarkus.io/guides/credentials-provider)。但它仅在初始化期间运行。请参阅下面的配置(附加在 application.yml 中):

    datasource:
      credentials-provider: custom
      credentials-provider-name: custom-credentials-provider

但它只在启动时执行。所以我仍然有同样的问题。

我还阅读了在 Hibernate 中以编程方式设置属性UnsupportedOperationException:应用程序必须提供 JDBC 连接。但他们使用不同的配置源(hibernate.cfg.configsource)并且他们不使用Panache。

我还尝试在运行时设置新密码。我输入了密码

    @ConfigProperty(name = "quarkus.datasource.password")
    lateinit var password: String

    ... //  I fetch the new passord and change it.

但它也不起作用,因为它只修改配置文件的副本。如果我设法更改配置源,Panache 会使用正确的凭据重新建立新连接吗?

amazon-web-services kotlin database-connection config
1个回答
0
投票

我成功添加了一个自定义凭证提供程序,如下所示https://quarkus.io/guides/credentials-provider

我的错误是我们为开发和生产使用了不同的配置文件,并且我忘记在 application.yml 中添加生产中的配置。您可以将其添加到您的生产配置文件中,如下所示:

"%prod":
  quarkus:
    datasource:
      credentials-provider: custom
      credentials-provider-name: custom-credentials-provider

自定义凭证提供程序的示例:

package <WRITE YOUR PACKAGE HERE>

import io.quarkus.credentials.CredentialsProvider
import io.quarkus.credentials.CredentialsProvider.PASSWORD_PROPERTY_NAME
import io.quarkus.credentials.CredentialsProvider.USER_PROPERTY_NAME
import javax.enterprise.context.ApplicationScoped
import javax.inject.Inject
import javax.inject.Named

@ApplicationScoped
@Named("custom-credentials-provider")
class CustomCredentialsProvider : CredentialsProvider {

    @Inject
    private lateinit var config: DataSourceConfigSource

    override fun getCredentials(credentialsProviderName: String): Map<String, String?> {
        return mutableMapOf(
            Pair(PASSWORD_PROPERTY_NAME, <Add your logic to get the secret from the vault>),
            Pair(USER_PROPERTY_NAME, <Add your logic to get the secret from the vault>)
        )
    }
}

为什么这个解决方案可以与秘密轮换一起使用?调试hibernate连接后,您可以看到hibernate在每个事务之后释放每个jdbc连接。因此,每个新事务都会创建一个新连接,通过自定义凭据提供程序提取更新的机密。这可能会带来额外的网络或保管库管理器成本(在我的例子中是 AWS 秘密管理器)。使用 IAM 身份验证而不是密码身份验证可能是一种更具成本效益的选择,因为您可以在更长的时间内维护令牌 https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html

© www.soinside.com 2019 - 2024. All rights reserved.