【问题标题】:SSH tunnel to Sequelize PostgreSQL databaseSSH 隧道到 Sequelize PostgreSQL 数据库
【发布时间】:2019-12-11 07:13:53
【问题描述】:

我正在尝试访问我们隐藏在堡垒 EC2 实例后面的远程数据库 (AWS RDS) 之一。我可以通过我的 SQL 客户端轻松访问数据库,但无法通过我正在构建的 CLI 工具访问它(使用Sequelizetunnel-ssh)。我一直在关注这个GitHub Gist,但它在任何地方都使用相同的值,不幸的是,这很令人困惑。

我承认总体上对 SSH 隧道的理解很差,这在下面的示例中可能很明显。我的配置有问题吗?


数据库配置

Host:     wdXXXXXXXXXXXX.XXXXXXXXX.XX-XXXXX-X.rds.amazonaws.com
Port:     5432
User:     [DB_USER]
Password: [DB_PASSWORD]
Database: [DB_NAME]

堡垒配置

Server:   35.183.XX.XXX
Port:     22
Password:
SSH Key:  ~/.ssh/id_rsa.aws
const config = {
  // I don't need to specify any local values, do I?
  // localHost: "127.0.0.1",
  // localPort: 5432,

  // This should be bastion config, correct?
  username: "ec2-user",
  host: 35.183.XX.XXX,
  port: 22,
  privateKey: require("fsf").readFileSync("/path/to/ssh/key"),

  // This should be destination (database) config, correct?
  dstHost: wdXXXXXXXXXXXX.XXXXXXXXX.XX-XXXXX-X.rds.amazonaws.com,
  dstPort: 5432
};

// NOTE: If I don't have an "await" here, nothing seems to run inside the function itself (no consoles, etc)
const server = await tunnel(config, async (error, server) => {
  if (error) return console.error(error);

  const db = new Sequelize(DB_NAME, DB_USER, DB_PASSWORD, {
    dialect: "postgres",
    // NOTE: If this is already the destination in the SSH tunnel, should I use it again vs localhost?
    host: "wdXXXXXXXXXXXX.XXXXXXXXX.XX-XXXXX-X.rds.amazonaws.com",
    port: 5432
  });

  db.authenticate().then(async () => {
    const orgs = await db.organization.findAll();

    console.log("Successful query", orgs);
  }).catch(err => {
    console.error("DB auth error": err);
  });
});

我上面的配置有问题吗?我在隧道配置中使用的值是否会影响我对隧道的理解?

另外,为什么似乎没有调用隧道回调除非await 函数(这似乎根本不是 Promise)?

附:还有这个 Sequelize GitHub 问题提到通过 SSH 隧道连接 Sequelize,但没有给出示例。

【问题讨论】:

    标签: database sequelize.js ssh-tunnel


    【解决方案1】:

    我最终弄明白了这个问题并且能够解决问题(在它开始后 12 小时)...数据库和堡垒配置在技术上是正确的,但是我错误地传递了一些值(由于对 SSH 的理解有缺陷)隧道)。

    数据库配置

    Host:     wdXXXXXXXXXXXX.XXXXXXXXX.XX-XXXXX-X.rds.amazonaws.com
    Port:     5432
    User:     [DB_USER]
    Password: [DB_PASSWORD]
    Database: [DB_NAME]
    

    堡垒配置

    Server:   35.183.XX.XXX
    Port:     22
    Password:
    SSH Key:  ~/.ssh/id_rsa.aws
    
    const config = {
      // I have confirmed that the local values are unnecessary (defaults work)
    
      // Configuration for SSH bastion
      username: "ec2-user",
      host: 35.183.XX.XXX,
      port: 22,
      privateKey: require("fs").readFileSync("/path/to/ssh/key"),
    
      // Configuration for destination (database)
      dstHost: wdXXXXXXXXXXXX.XXXXXXXXX.XX-XXXXX-X.rds.amazonaws.com,
      dstPort: 5432
    };
    
    // NOTE: Moved to its own function, refactor likely fixed a few issues along the way
    const getDB = () => new Promise((resolve, reject) => {
      const tnl = await tunnel(config, async error => {
        if (error) return reject(error);
    
        const db = new Sequelize(DB_NAME, DB_USER, DB_PASSWORD, {
          dialect: "postgres",
          // NOTE: This is super important as the tunnel has essentially moved code execution to the database server already...
          host: "localhost",
          port: 5432
        });
    
        return resolve(db);
      });
    });
    

    最后,主要更改是在 Sequelize 配置中使用 localhost 作为数据库实例上“出现”的 SSH 隧道,因此它应该引用自身。可能还有一些其他必要的调整(据我所知,我曾尝试过),但最终我完好无损地出现了。

    【讨论】:

    • 我正在使用这个确切的步骤,但我仍然无法访问数据库。它给了我这个错误 - 未捕获的异常:错误:所有配置的身份验证方法都失败了。有人可以帮我理解错误
    • 我也是,虽然我的做法和你一模一样,但我无法连接数据库:(
    • 我认为您需要在隧道初始化代码中添加keepAlive: true 选项,否则它会在第一次连接尝试后失败
    猜你喜欢
    • 2014-10-04
    • 2021-12-02
    • 2016-04-30
    • 1970-01-01
    • 2013-05-26
    • 2015-03-01
    • 2014-07-20
    • 1970-01-01
    • 2013-04-05
    相关资源
    最近更新 更多