sharp-db
Version:
Classes for running SQL and building select queries for MySQL in Node
82 lines (77 loc) • 2.19 kB
JavaScript
const os = require('os');
const fs = require('fs');
const Client = require('ssh2').Client;
/**
* Class to allow connecting to a DB through an ssh tunnel
*/
class Ssh {
/**
* Specify connection details including, host, port, user, privateKey
* @param {Object} [config] Configuration to send to npm's ssh2
*/
constructor(config = {}) {
const env = process.env;
this.config = {
...config,
host: config.host || env.DB_SSH_HOST || 'localhost',
port: config.port || env.DB_SSH_PORT || 22,
user: config.user || env.DB_SSH_USER,
localPort: config.localPort || env.DB_SSH_LOCAL_PORT || 12347,
};
if (config.privateKey || env.DB_SSH_PRIVATE_KEY) {
this.config.privateKey = config.privateKey || env.DB_SSH_PRIVATE_KEY;
if (this.config.privateKey.match(/\.pem$/)) {
const pkeyPath = this.config.privateKey.replace(/^~/, os.homedir());
if (!fs.existsSync(pkeyPath)) {
throw new Error(`Private key file not found at "${pkeyPath}".`);
}
this.config.privateKey = fs.readFileSync(pkeyPath, {
encoding: 'utf8',
});
}
} else if (config.password || env.DB_SSH_PASSWORD) {
this.config.password = config.password || env.DB_SSH_PASSWORD;
}
}
/**
* Setup a tunnel for the given Db instance
* @param {Db} db A Db instance
* @returns {Promise} Resolves when tunnel is established
*/
tunnelTo(db) {
return new Promise((resolve, reject) => {
if (!db.config || !db.config.host || !db.config.port) {
reject(new Error('Db config must have host and port.'));
}
this.connection = new Client();
this.connection.on('ready', () => {
this.connection.forwardOut(
'127.0.0.1',
this.config.localPort,
db.config.host,
db.config.port,
(err, stream) => {
if (err) {
this.end();
return reject(err);
}
// override db host, since we're operating from within the SSH tunnel
db.config.host = 'localhost';
db.config.stream = stream;
resolve();
}
);
});
this.connection.connect(this.config);
});
}
/**
* Close the ssh tunnel
*/
end() {
if (this.connection) {
this.connection.end();
}
}
}
module.exports = Ssh;