mui / toolpad

Toolpad: Full stack components and low-code builder for dashboards and internal apps.
https://mui.com/toolpad/
MIT License
1.29k stars 285 forks source link

Support SSH tunnel #869

Open oliviertassinari opened 2 years ago

oliviertassinari commented 2 years ago

Duplicates

Latest version

Summary 💡

Make it possible to connect to a database using a bastion.

Examples 🌈

Screenshot 2022-08-29 at 16 33 53 Screenshot 2022-10-13 at 22 53 09

Motivation 🔦

https://serverfault.com/questions/283172/is-it-safe-to-open-port-3306-in-firewall-for-external-mysql-connection

oliviertassinari commented 1 year ago

I had this problem trying to access the MUI Store MySQL panel. Normally, we would use our Bastion with SSH tunnel. I couldn't so instead, I used https://api.ipify.org?format=json to find Toolpad's IP and whitelisted it to access MySQL.

Screenshot 2023-01-27 at 12 46 52

But on render.com, the IP of the instance is not stable, so I can't easily whitelist the IPs.


In pipedream, I'm doing it manually as they don't support it natively:

module.exports = defineComponent({
  props: {
    mysql: {
      type: "app",
      app: "mysql",
    }
  },
  async run({steps, $}) {
    const mysql = require('mysql2/promise');
    const SSH2Promise = require('ssh2-promise');

    const { host, port, username, password, database } = this.mysql.$auth

    const ssh = new SSH2Promise({
      host: bastionHost,
      port: bastionPort,
      username: bastionUsername,
      privateKey: bastionPipedreamPrivateKey,
    });

    const tunnel = await ssh.addTunnel({
      remoteAddr: host,
      remotePort: port,
    })

    const connection = await mysql.createConnection({
      host: 'localhost',
      port: tunnel.localPort,
      user: username,
      password,
      database,
    });

    const [rows] = await connection.execute(
      // Note - manually created orders might not have u.id if created as guest.
      // That's okay, as emailing a customer or reseller AP mailbox isn't helpful
      `SELECT
          post.id as orderID,
          post.post_date as date,`,
      [fromDateString, toDateString]
    );

    await connection.end();
    await ssh.close();

    return {};
  },
})