使用Java连接池进行AWS IAM数据库身份验证

使用Java连接池进行AWS IAM数据库身份验证,java,amazon-web-services,amazon-rds,amazon-iam,Java,Amazon Web Services,Amazon Rds,Amazon Iam,我正在寻找一个Java数据库连接池,它允许我对我的Aurora MySQL使用AWS IAM数据库身份验证。该池应该能够使用Tomcat context.xml文件 我已经研究了Tomcat DBCP、dbcp2、HikariCP和c3p0。但它们似乎都表明用户名和密码在应用程序启动时是已知的,并且在应用程序的生命周期中不会更改 对于IAM数据库身份验证,凭据每15分钟更改一次,因此池需要在创建新连接时向AWS IAM请求新凭据(凭据可以缓存几分钟) 这是在任何Java连接池中实现的吗?或者你有

我正在寻找一个Java数据库连接池,它允许我对我的Aurora MySQL使用AWS IAM数据库身份验证。该池应该能够使用Tomcat context.xml文件

我已经研究了Tomcat DBCP、dbcp2、HikariCP和c3p0。但它们似乎都表明用户名和密码在应用程序启动时是已知的,并且在应用程序的生命周期中不会更改

对于IAM数据库身份验证,凭据每15分钟更改一次,因此池需要在创建新连接时向AWS IAM请求新凭据(凭据可以缓存几分钟)


这是在任何Java连接池中实现的吗?或者你有没有办法让它工作起来?

我最近也遇到了同样的问题。。。。我使用HikariCP连接池,到目前为止,它还不支持此功能。幸运的是,我用这个工具找到了一个PR:

我建议您制作一个项目fork并在官方存储库接受此PR之前使用它

我对这一点的执行:

public DataSource setup() throws Exception {
Supplier<String> passwordSupplier = () -> {
    return this.generateAuthToken(host, port, user);
}; 
com.zaxxer.hikari.HikariDataSource dataSource = new com.zaxxer.hikari.HikariDataSource();
dataSource.setPasswordSupplier(passwordSupplier); ...
因为您的池连接不能使用RDS Iam Auth超过15分钟


祝你好运。

我也不得不使用节点js lambda和MySql RDS来面对这个问题。我们使用了一个连接池,因此我们实现了一个解决方案,该解决方案创建了一个未来的日期时间,我们可以检查连接是否即将到期,无论何时从连接池请求连接。这个日期时间是15分钟减去连接池初始化后的一些抖动

因此,获取连接池(以获取连接)的过程如下所示:

const getPool = async (): Promise<DbConnectionPool> => {
  if (isRdsIamTokenCloseToExpiring()) {
    await poolHolder.lock.acquire();
    try {
      // if, after having acquired lock, thread pool is still about to expire...    
      if (isRdsIamTokenCloseToExpiring()) {     
        await closeConnectionsInPool();
        await initializeConnectionPool();
      }
    } finally {
      poolHolder.lock.release();
    }
  }
  if (!poolHolder.pool) {
    throw new Error('pool holder is null - this should never happen');
  } else {
    return poolHolder.pool;
  }
};
const getPool=async():Promise=>{ if(isRdsIamTokenCloseToExpiring()){ 等待poolHolder.lock.acquire(); 试一试{ //若在获得锁后,线程池仍将过期。。。 如果(isRdsIamTokenCloseToExpiring()){ 等待关闭连接输入工具(); 等待初始化连接池(); } }最后{ poolHolder.lock.release(); } } 如果(!poolHolder.pool){ 抛出新错误('pool holder为null-这永远不会发生'); }否则{ 返回poolHolder.pool; } }; 因为我们有多个并发异步线程试图获得连接,所以我们必须引入一个信号量来控制池的重新初始化。总而言之,这样做比使用用户名和密码更麻烦,但更安全


要回答Isen Ng的上述评论(我没有代表直接回答),RDS IAM令牌过期的连接将停止工作

我知道这是一个较老的问题,但经过一番搜索后,我找到了一种非常简单的方法,现在可以使用MariaDB驱动程序来实现这一点。在版本2.5中,他们在驱动程序中添加了一个。它将自动处理令牌的生成、缓存和刷新。您可以这样激活它:

jdbc:mariadb://host/db?credentialType=AWS-IAM&useSsl&serverSslCert=/somepath/rds组合ca bundle.pem

我已经使用HikariCP连接池进行了测试,它对我很有效。确保您使用的是MariaDB驱动程序(不是MySQL),并将
maxLifetime
设置为600000ms(驱动程序缓存令牌10分钟)


希望这对其他人有所帮助-我在网上找到的大多数示例都涉及自定义代码、后台线程等-但是使用新的驱动程序功能要容易得多

有一个很酷的方法。请参阅您确定
dataSource.setMaxLifetime(15*60*1000)是必需的吗?我一直认为,一旦物理连接打开,密码是否更改/令牌是否无效并不重要。新连接将需要新密码/有效令牌,但现有连接将继续工作。当我有时间的时候,我将在本周测试这个假设。
const getPool = async (): Promise<DbConnectionPool> => {
  if (isRdsIamTokenCloseToExpiring()) {
    await poolHolder.lock.acquire();
    try {
      // if, after having acquired lock, thread pool is still about to expire...    
      if (isRdsIamTokenCloseToExpiring()) {     
        await closeConnectionsInPool();
        await initializeConnectionPool();
      }
    } finally {
      poolHolder.lock.release();
    }
  }
  if (!poolHolder.pool) {
    throw new Error('pool holder is null - this should never happen');
  } else {
    return poolHolder.pool;
  }
};