SSL support

This commit is contained in:
Jan Prochazka 2021-02-14 09:11:40 +01:00
parent 417ec9fcd2
commit d08fc85459
3 changed files with 58 additions and 29 deletions

View File

@ -1,45 +1,54 @@
const { SSHConnection } = require('node-ssh-forward');
const portfinder = require('portfinder');
const fs = require('fs-extra');
const { decryptConnection } = require('./crypting');
const { getSshTunnel } = require('./sshTunnel');
const { getSshTunnelProxy } = require('./sshTunnelProxy');
async function connectUtility(driver, storedConnection) {
let connection = decryptConnection(storedConnection);
const connection = {
...decryptConnection(storedConnection),
};
if (connection.useSshTunnel) {
const tunnel = await getSshTunnelProxy(connection);
if (tunnel.state == 'error') {
throw new Error(tunnel.message);
}
// const sshConfig = {
// endHost: connection.sshHost || '',
// endPort: connection.sshPort || 22,
// bastionHost: '',
// agentForward: false,
// passphrase: undefined,
// username: connection.sshLogin,
// password: connection.sshPassword,
// skipAutoPrivateKey: true,
// noReadline: true,
// };
// const sshConn = new SSHConnection(sshConfig);
// const localPort = await portfinder.getPortPromise({ port: 10000, stopPort: 60000 });
// // workaround for `getPortPromise` not releasing the port quickly enough
// await new Promise(resolve => setTimeout(resolve, 500));
// const tunnelConfig = {
// fromPort: localPort,
// toPort: connection.port,
// toHost: connection.server,
// };
// const tunnel = await sshConn.forward(tunnelConfig);
// console.log(`Created SSH tunnel to ${connection.sshHost}-${connection.server}:${connection.port}, using local port ${localPort}`)
connection.server = '127.0.0.1';
connection.port = tunnel.localPort;
}
connection = {
...connection,
server: '127.0.0.1',
port: tunnel.localPort,
};
if (!connection.port && driver.defaultPort) connection.port = driver.defaultPort.toString();
// SSL functionality - copied from https://github.com/beekeeper-studio/beekeeper-studio
if (connection.useSsl) {
connection.ssl = {};
if (connection.sslCaFile) {
connection.ssl.ca = await fs.readFile(connection.sslCaFile);
}
if (connection.sslCertFile) {
connection.ssl.cert = await fs.readFile(connection.sslCertFile);
}
if (connection.sslKeyFile) {
connection.ssl.key = await fs.readFile(connection.sslKeyFile);
}
if (!connection.ssl.key && !connection.ssl.ca && !connection.ssl.cert) {
// TODO: provide this as an option in settings
// or per-connection as 'reject self-signed certs'
// How it works:
// if false, cert can be self-signed
// if true, has to be from a public CA
// Heroku certs are self-signed.
// if you provide ca/cert/key files, it overrides this
connection.ssl.rejectUnauthorized = false;
} else {
connection.ssl.rejectUnauthorized = connection.sslRejectUnauthorized;
}
}
const conn = await driver.connect(connection);

View File

@ -98,6 +98,7 @@ function DriverFields({ extensions }) {
name="port"
disabled={disabledFields.includes('port')}
templateProps={{ noMargin: true }}
placeholder={driver && driver.defaultPort}
/>
</FlexCol3>
</FormRowLarge>
@ -235,6 +236,22 @@ function SshTunnelFields() {
);
}
function SslFields() {
const { values } = useForm();
const { useSsl } = values;
const electron = getElectron();
return (
<>
<FormCheckboxField label="Use SSL" name="useSsl" />
<FormElectronFileSelector label="CA Cert (optional)" name="sslCaFile" disabled={!useSsl || !electron} />
<FormElectronFileSelector label="Certificate (optional)" name="sslCertFile" disabled={!useSsl || !electron} />
<FormElectronFileSelector label="Key file (optional)" name="sslKeyFile" disabled={!useSsl || !electron} />
<FormCheckboxField label="Reject unauthorized" name="sslRejectUnauthorized" disabled={!useSsl} />
</>
);
}
export default function ConnectionModal({ modalState, connection = undefined }) {
const [sqlConnectResult, setSqlConnectResult] = React.useState(null);
const extensions = useExtensions();
@ -288,6 +305,9 @@ export default function ConnectionModal({ modalState, connection = undefined })
<TabPage label="SSH Tunnel" key="sshTunnel">
<SshTunnelFields />
</TabPage>
<TabPage label="SSL" key="ssl">
<SslFields />
</TabPage>
</TabControl>
</ModalContent>

View File

@ -119,7 +119,7 @@ export function FormCheckboxField({ label, templateProps = undefined, ...other }
<FieldTemplate
label={label}
type="checkbox"
onLabelClick={() => setFieldValue(other.name, !values[other.name])}
onLabelClick={other.disabled ? undefined : () => setFieldValue(other.name, !values[other.name])}
{...templateProps}
>
<FormCheckboxFieldRaw {...other} />