带有 AWS Lambda 和 IAM 身份验证的 MyBatis-guice 因 PAM 身份验证错误而失败

时间:2021-06-15 11:38:51

标签: java postgresql aws-lambda mybatis pam

我正在尝试使用 IAM 身份验证和 MyBatis-Guice 连接到 RDS Aurora Postgres 实例以运行一些插入语句。该设置最初工作正常。但是,一段时间后,lambda 调用失败并显示 FATAL: PAM authentication failed for user "xxx"。这通常发生在并发调用时。但是,接下来的调用成功了。

这是我的 DAO 方法:

@Transactional(executorType=ExecutorType.BATCH, isolationType=Isolation.READ_COMMITTED)
public void insertEntities(List<Entity> entities) {
    for(Entity entity: entities) {
        myMapper.insert(entity);
    }
}

不应发生此错误,因为 IAM 令牌和 Lambda 都有 15 分钟的时间限制。
另外,查看源代码,我看到 dataSourceProvider 绑定到 MyBatisModule 中 Singleton 范围内的 DataSource。我的猜测是,某些并发 lambda getAuthToken() 调用会更改 postgres 角色的预期令牌,并且当调用任何其他“暖”并发 lambda 时(与更改密码的 lambda 一起)并打开一个新的托管会话使用旧令牌配置的数据源,它收到 PAM authentication 错误。

我该如何缓解这种情况?

1 个答案:

答案 0 :(得分:0)

我每次调用 Lambda 函数时都会设置密码。我对我的 DAO 方法进行了一些更改,并使用了 SqlSession 而不是 Mappers。这是为了避免在 mybatis-guice 中直接使用带有 @Transactional 的 Mapper 方法时底层 SqlSessionManager 所做的 SqlSession 缓存。这里用到的SqlSessionFactory是Singleton作用域,注入到DAO实例中。

public void insertEntities(List<Entity> entites) {
  try(SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH, TransactionIsolationLevel.READ_COMMITTED) {
    try {
      MyMapper myMapper = session.getMapper(MyMapper.class);
      // do something
      session.commit();
    } catch(Exception e) {
      session.rollback();
      throw e;
    }
  }
}

并且在每次调用时,我将密码设置为数据源中的 IAM 身份验证令牌。

MyDataSource dataSource = (MyDataSource) sqlSessionFactory.getConfiguration().getEnvironment().getDataSource();
dataSource.setPassword(generator.getAuthToken(request));

现在每当调用 Lambda 函数时,数据源都会有一个新的身份验证令牌,并且能够连接到数据库。