Skip to content

Commit

Permalink
chore: cleanup node14 unneeded code
Browse files Browse the repository at this point in the history
  • Loading branch information
jackwotherspoon committed Dec 16, 2024
1 parent c2c1cb7 commit 619fba7
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 260 deletions.
1 change: 0 additions & 1 deletion .npmrc

This file was deleted.

2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@
"@sequelize/core": "^7.0.0-alpha.29",
"@types/node": "^22.0.0",
"@types/pg": "^8.10.1",
"@types/semver": "^7.5.0",
"@types/tap": "^18.0.0",
"@types/tedious": "^4.0.9",
"@typescript-eslint/eslint-plugin": "^7.0.0",
Expand All @@ -71,7 +70,6 @@
"mysql2": "^3.2.0",
"nock": "^13.3.0",
"pg": "^8.10.0",
"semver": "^7.5.1",
"tap": "^21.0.0",
"tedious": "^16.1.0",
"typeorm": "^0.3.19",
Expand Down
27 changes: 0 additions & 27 deletions scripts/tap16-adapter.js

This file was deleted.

87 changes: 18 additions & 69 deletions src/crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,54 +18,6 @@ import {SslCert} from './ssl-cert';
import {cryptoModule} from './node-crypto';
import {CloudSQLConnectorError} from './errors';

// The following is a fallback certificate parser for node14 to work around
// its lack of support to the X509Certificate class parser, this block of code
// can be safely removed once node14 is no longer supported, along with any
// `node14ParseCert` call and its unit tests.
// --- node@14 cert parse fallback start
import net from 'node:net';
import tls from 'node:tls';

const node14ParseCert = (cert: string): SslCert => {
const isPeerCertificate = (
obj: object | tls.PeerCertificate
): obj is tls.PeerCertificate =>
(obj as tls.PeerCertificate).valid_to !== undefined;

let socket;
let parsed;
try {
socket = new tls.TLSSocket(new net.Socket(), {
secureContext: tls.createSecureContext({cert}),
});
parsed = socket.getCertificate();
} catch (err: unknown) {
throw new CloudSQLConnectorError({
message: 'Failed to parse as X.509 certificate.',
code: 'EPARSESQLADMINEPH',
errors: [err as Error],
});
}

if (parsed && isPeerCertificate(parsed)) {
const expirationTime = parsed.valid_to;
socket.destroy();
socket = undefined;
parsed = undefined;

return {
cert,
expirationTime,
};
}
/* c8 ignore next 5 */
throw new CloudSQLConnectorError({
message: 'Could not read ephemeral certificate.',
code: 'EPARSESQLADMINEPH',
});
};
// --- node@14 cert parse fallback end

export async function generateKeys(): Promise<RSAKeys> {
const crypto = await cryptoModule();
const keygen = promisify(crypto.generateKeyPair);
Expand All @@ -90,27 +42,24 @@ export async function generateKeys(): Promise<RSAKeys> {

export async function parseCert(cert: string): Promise<SslCert> {
const {X509Certificate} = await cryptoModule();
if (X509Certificate) {
try {
const parsed = new X509Certificate(cert);
if (parsed && parsed.validTo) {
return {
cert,
expirationTime: parsed.validTo,
};
}

throw new CloudSQLConnectorError({
message: 'Could not read ephemeral certificate.',
code: 'EPARSESQLADMINEPH',
});
} catch (err: unknown) {
throw new CloudSQLConnectorError({
message: 'Failed to parse as X.509 certificate.',
code: 'EPARSESQLADMINEPH',
errors: [err as Error],
});
try {
const parsed = new X509Certificate(cert);
if (parsed && parsed.validTo) {
return {
cert,
expirationTime: parsed.validTo,
};
}

throw new CloudSQLConnectorError({
message: 'Could not read ephemeral certificate.',
code: 'EPARSESQLADMINEPH',
});
} catch (err: unknown) {
throw new CloudSQLConnectorError({
message: 'Failed to parse as X.509 certificate.',
code: 'EPARSESQLADMINEPH',
errors: [err as Error],
});
}
return node14ParseCert(cert);
}
105 changes: 49 additions & 56 deletions system-test/tedious-connect.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,69 +13,62 @@
// limitations under the License.

const t = require('tap');
const semver = require('semver');
const {Connector} = require('@google-cloud/cloud-sql-connector');
const {Connection, Request} = require('tedious');

t.test(
'open connection and run basic sqlserver commands',
// the connector-supported versions of tedious do not support node14
{skip: semver.lt(process.versions.node, '16.0.0')},
async t => {
// lazy-load tedious here in order to allow for skipping node14
const {Connection, Request} = require('tedious');
const connector = new Connector();
const clientOpts = await connector.getTediousOptions({
instanceConnectionName: process.env.SQLSERVER_CONNECTION_NAME,
ipType: 'PUBLIC',
});
const connection = new Connection({
server: '0.0.0.0',
authentication: {
type: 'default',
options: {
userName: process.env.SQLSERVER_USER,
password: process.env.SQLSERVER_PASS,
},
},
t.test('open connection and run basic sqlserver commands', async t => {
const connector = new Connector();
const clientOpts = await connector.getTediousOptions({
instanceConnectionName: process.env.SQLSERVER_CONNECTION_NAME,
ipType: 'PUBLIC',
});
const connection = new Connection({
server: '0.0.0.0',
authentication: {
type: 'default',
options: {
...clientOpts,
port: 9999,
database: process.env.SQLSERVER_DB,
userName: process.env.SQLSERVER_USER,
password: process.env.SQLSERVER_PASS,
},
});
},
options: {
...clientOpts,
port: 9999,
database: process.env.SQLSERVER_DB,
},
});

await new Promise((res, rej) => {
connection.connect(err => {
if (err) {
return rej(err);
}
res();
});
await new Promise((res, rej) => {
connection.connect(err => {
if (err) {
return rej(err);
}
res();
});
});

const res = await new Promise((res, rej) => {
let result;
const req = new Request('SELECT GETUTCDATE()', err => {
if (err) {
throw err;
}
});
req.on('error', err => {
rej(err);
});
req.on('row', columns => {
result = columns;
});
req.on('requestCompleted', () => {
res(result);
});
connection.execSql(req);
const res = await new Promise((res, rej) => {
let result;
const req = new Request('SELECT GETUTCDATE()', err => {
if (err) {
throw err;
}
});
req.on('error', err => {
rej(err);
});
req.on('row', columns => {
result = columns;
});
req.on('requestCompleted', () => {
res(result);
});
connection.execSql(req);
});

const [{value: utcDateResult}] = res;
t.ok(utcDateResult.getTime(), 'should have valid returned date object');
const [{value: utcDateResult}] = res;
t.ok(utcDateResult.getTime(), 'should have valid returned date object');

connection.close();
connector.close();
}
);
connection.close();
connector.close();
});
91 changes: 43 additions & 48 deletions system-test/tedious-connect.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,62 +13,57 @@
// limitations under the License.

import t from 'tap';
import semver from 'semver';
import {Connector} from '@google-cloud/cloud-sql-connector';

import { Connector } from '@google-cloud/cloud-sql-connector';
import { Connection, Request }
t.test(
'open connection and run basic sqlserver commands',
// the connector-supported versions of tedious do not support node14
{skip: semver.lt(process.versions.node, '16.0.0')},
async t => {
// dynamically load tedious in order to allow for skipping node14
const {Connection, Request} = await import('tedious');
const connector = new Connector();
const clientOpts = await connector.getTediousOptions({
instanceConnectionName: process.env.SQLSERVER_CONNECTION_NAME,
ipType: 'PUBLIC'
});
const connection = new Connection({
server: '0.0.0.0',
authentication: {
type: 'default',
const connector = new Connector();
const clientOpts = await connector.getTediousOptions({
instanceConnectionName: process.env.SQLSERVER_CONNECTION_NAME,
ipType: 'PUBLIC'
});
const connection = new Connection({
server: '0.0.0.0',
authentication: {
type: 'default',
options: {
userName: process.env.SQLSERVER_USER,
password: process.env.SQLSERVER_PASS,
},
},
options: {
userName: process.env.SQLSERVER_USER,
password: process.env.SQLSERVER_PASS,
...clientOpts,
port: 9999,
database: process.env.SQLSERVER_DB,
},
},
options: {
...clientOpts,
port: 9999,
database: process.env.SQLSERVER_DB,
},
})
})

await new Promise((res, rej) => {
connection.connect(err => {
if (err) {
return rej(err)
}
res()
await new Promise((res, rej) => {
connection.connect(err => {
if (err) {
return rej(err)
}
res()
})
})
})

const res = await new Promise((res, rej) => {
let result;
const req = new Request('SELECT GETUTCDATE()', (err) => {
if (err) {
throw err;
}
const res = await new Promise((res, rej) => {
let result;
const req = new Request('SELECT GETUTCDATE()', (err) => {
if (err) {
throw err;
}
})
req.on('error', (err) => { rej(err); });
req.on('row', (columns) => { result = columns; });
req.on('requestCompleted', () => { res(result); });
connection.execSql(req);
})
req.on('error', (err) => { rej(err); });
req.on('row', (columns) => { result = columns; });
req.on('requestCompleted', () => { res(result); });
connection.execSql(req);
})

const [{value: utcDateResult}] = res;
t.ok(utcDateResult.getTime(), 'should have valid returned date object');
const [{ value: utcDateResult }] = res;
t.ok(utcDateResult.getTime(), 'should have valid returned date object');

connection.close();
connector.close();
});
connection.close();
connector.close();
});
Loading

0 comments on commit 619fba7

Please sign in to comment.