From 424f432d48a1605430ce33763e5916928160c11e Mon Sep 17 00:00:00 2001 From: Giovanni Minotti Date: Mon, 31 Aug 2020 13:56:35 +0200 Subject: [PATCH 01/12] HTTPS Tests --- package.json | 4 ++ test/helpers/create-cert-test-server.ts | 67 +++++++++++++++++++++++++ test/helpers/with-server.ts | 19 +++++-- test/https.ts | 15 +++++- 4 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 test/helpers/create-cert-test-server.ts diff --git a/package.json b/package.json index 9f3d78441..c0baef9e4 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,8 @@ "@types/express": "^4.17.7", "@types/node": "^14.6.0", "@types/node-fetch": "^2.5.7", + "@types/pem": "^1.9.5", + "@types/pify": "^3.0.2", "@types/request": "^2.48.5", "@types/sinon": "^9.0.5", "@types/tough-cookie": "^4.0.0", @@ -81,6 +83,8 @@ "np": "^6.4.0", "nyc": "^15.1.0", "p-event": "^4.2.0", + "pem": "^1.14.4", + "pify": "^5.0.0", "sinon": "^9.0.3", "slow-stream": "0.0.4", "tempy": "^0.6.0", diff --git a/test/helpers/create-cert-test-server.ts b/test/helpers/create-cert-test-server.ts new file mode 100644 index 000000000..40e7a97b1 --- /dev/null +++ b/test/helpers/create-cert-test-server.ts @@ -0,0 +1,67 @@ +import https = require('https'); +import express = require('express'); +import pify = require('pify'); +import pem = require('pem'); + +const createCertTestServer = async () => { + const createCSR = pify(pem.createCSR); + const createCertificate = pify(pem.createCertificate); + + const caCSRResult = await createCSR({commonName: 'authority'}); + const caResult = await createCertificate({ + csr: caCSRResult.csr, + clientKey: caCSRResult.clientKey, + selfSigned: true + }); + const caKey = caResult.clientKey; + const caCert = caResult.certificate; + + const serverCSRResult = await createCSR({commonName: 'localhost'}); + const serverResult = await createCertificate({ + csr: serverCSRResult.csr, + clientKey: serverCSRResult.clientKey, + serviceKey: caKey, + serviceCertificate: caCert + }); + const serverKey = serverResult.clientKey; + const serverCert = serverResult.certificate; + + const clientCSRResult = await createCSR({commonName: 'client'}); + const clientResult = await createCertificate({ + csr: clientCSRResult.csr, + clientKey: clientCSRResult.clientKey, + serviceKey: caKey, + serviceCertificate: caCert + }); + const {clientKey} = clientResult; + const clientCert = clientResult.certificate; + + const server = express(); + (server as any).https = https.createServer( + { + key: serverKey, + cert: serverCert, + ca: caCert, + requestCert: true, + rejectUnauthorized: true + }, + server + ); + + server.set('etag', false); + + await pify((server as any).https.listen.bind((server as any).https))(); + + (server as any).caCert = caCert; + (server as any).clientCert = clientCert; + (server as any).clientKey = clientKey; + (server as any).sslPort = (server as any).https.address().port; + (server as any).sslUrl = `https://localhost:${((server as any).sslPort as number)}`; + + (server as any).close = () => + pify((server as any).https.close.bind((server as any).https))(); + + return server; +}; + +export default createCertTestServer; diff --git a/test/helpers/with-server.ts b/test/helpers/with-server.ts index 9b2384545..e1f822bcc 100644 --- a/test/helpers/with-server.ts +++ b/test/helpers/with-server.ts @@ -3,6 +3,7 @@ import * as test from 'ava'; import is from '@sindresorhus/is'; import http = require('http'); import tempy = require('tempy'); +import createCertTestServer from './create-cert-test-server'; import createTestServer = require('create-test-server'); import FakeTimers = require('@sinonjs/fake-timers'); import got, {InstanceDefaults} from '../../source'; @@ -11,11 +12,11 @@ import {ExtendedGot, ExtendedHttpServer, ExtendedTestServer, GlobalClock, Instal export type RunTestWithServer = (t: test.ExecutionContext, server: ExtendedTestServer, got: ExtendedGot, clock: GlobalClock) => Promise | void; export type RunTestWithSocket = (t: test.ExecutionContext, server: ExtendedHttpServer) => Promise | void; -const generateHook = ({install, options: testServerOptions}: {install?: boolean; options?: unknown}): test.Macro<[RunTestWithServer]> => async (t, run) => { +const generateHook = ({install, selfSigned, options: testServerOptions}: {install?: boolean; selfSigned?: boolean; options?: unknown}): test.Macro<[RunTestWithServer]> => async (t, run) => { const clock = install ? FakeTimers.install() : FakeTimers.createClock() as GlobalClock; // Re-enable body parsing to investigate https://github.com/sindresorhus/got/issues/1186 - const server = await createTestServer(is.plainObject(testServerOptions) ? testServerOptions : { + const server = await (selfSigned ? createCertTestServer : createTestServer)(is.plainObject(testServerOptions) ? testServerOptions : { bodyParser: { type: () => false }, @@ -42,9 +43,18 @@ const generateHook = ({install, options: testServerOptions}: {install?: boolean; }; const preparedGot = got.extend({prefixUrl: server.url, ...options}) as ExtendedGot; - preparedGot.secure = got.extend({prefixUrl: server.sslUrl, ...options}); + if (selfSigned) { + preparedGot.secure = got.extend({prefixUrl: server.sslUrl, https: { + certificateAuthority: (server as any).caCert, + key: (server as any).clientKey, + certificate: (server as any).clientCert, + rejectUnauthorized: true + }, ...options}); + } else { + preparedGot.secure = got.extend({prefixUrl: server.sslUrl, ...options}); + server.hostname = (new URL(server.url)).hostname; + } - server.hostname = (new URL(server.url)).hostname; server.sslHostname = (new URL(server.sslUrl)).hostname; try { @@ -59,6 +69,7 @@ const generateHook = ({install, options: testServerOptions}: {install?: boolean; }; export const withBodyParsingServer = generateHook({install: false, options: {}}); +export const withCertServer = generateHook({install: false, selfSigned: true, options: {}}); export default generateHook({install: false}); export const withServerAndFakeTimers = generateHook({install: true}); diff --git a/test/https.ts b/test/https.ts index d5a55866d..e8e825466 100644 --- a/test/https.ts +++ b/test/https.ts @@ -1,6 +1,6 @@ import test from 'ava'; import got, {CancelableRequest} from '../source'; -import withServer from './helpers/with-server'; +import withServer, {withCertServer} from './helpers/with-server'; import {DetailedPeerCertificate} from 'tls'; import pEvent from 'p-event'; @@ -226,3 +226,16 @@ test.serial('no double deprecated warning', withServer, async (t, server, got) = t.pass(); }); + +test('client certificate', withCertServer, async (t, server, got) => { + server.get('/', (request, response) => { + const cert = (request.socket as any).getPeerCertificate(true); + + t.is(cert.subject.CN, 'client'); + t.is(cert.issuer.CN, 'authority'); + + response.end('ok'); + }); + + t.truthy((await got.secure({})).body); +}); From 0e6058085af257403d890a72267ca80eaeb7e26b Mon Sep 17 00:00:00 2001 From: Giovanni Minotti Date: Mon, 31 Aug 2020 14:10:16 +0200 Subject: [PATCH 02/12] Fixed Readme index entry for HTTPS API --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 55b02e886..502f59f15 100644 --- a/readme.md +++ b/readme.md @@ -40,7 +40,7 @@ For browser usage, we recommend [Ky](https://github.com/sindresorhus/ky) by the - [Errors with metadata](#errors) - [JSON mode](#json-mode) - [WHATWG URL support](#url) -- [HTTPS API](#https) +- [HTTPS API](#advanced-https-api) - [Hooks](#hooks) - [Instances with custom defaults](#instances) - [Types](#types) From 03af191c9a249b714e4a3e43f757754aad864fc8 Mon Sep 17 00:00:00 2001 From: Giovanni Minotti Date: Mon, 31 Aug 2020 14:54:08 +0200 Subject: [PATCH 03/12] More tests --- test/helpers/create-cert-test-server.ts | 5 +- test/https.ts | 100 ++++++++++++++++++++++-- 2 files changed, 98 insertions(+), 7 deletions(-) diff --git a/test/helpers/create-cert-test-server.ts b/test/helpers/create-cert-test-server.ts index 40e7a97b1..f73fd55a7 100644 --- a/test/helpers/create-cert-test-server.ts +++ b/test/helpers/create-cert-test-server.ts @@ -33,7 +33,8 @@ const createCertTestServer = async () => { serviceKey: caKey, serviceCertificate: caCert }); - const {clientKey} = clientResult; + // eslint-disable-next-line prefer-destructuring + const clientKey = clientResult.clientKey; const clientCert = clientResult.certificate; const server = express(); @@ -43,7 +44,7 @@ const createCertTestServer = async () => { cert: serverCert, ca: caCert, requestCert: true, - rejectUnauthorized: true + rejectUnauthorized: false // This should be checked by the test }, server ); diff --git a/test/https.ts b/test/https.ts index e8e825466..50542762d 100644 --- a/test/https.ts +++ b/test/https.ts @@ -3,6 +3,8 @@ import got, {CancelableRequest} from '../source'; import withServer, {withCertServer} from './helpers/with-server'; import {DetailedPeerCertificate} from 'tls'; import pEvent from 'p-event'; +import pify = require('pify'); +import pem = require('pem'); test('https request without ca', withServer, async (t, server, got) => { server.get('/', (_request, response) => { @@ -229,13 +231,101 @@ test.serial('no double deprecated warning', withServer, async (t, server, got) = test('client certificate', withCertServer, async (t, server, got) => { server.get('/', (request, response) => { - const cert = (request.socket as any).getPeerCertificate(true); + const peerCertificate = (request.socket as any).getPeerCertificate(true); + peerCertificate.issuerCertificate = undefined; // Circular structure - t.is(cert.subject.CN, 'client'); - t.is(cert.issuer.CN, 'authority'); + response.json({ + authorized: (request.socket as any).authorized, + peerCertificate + }); + }); - response.end('ok'); + const response: any = await got.secure({}).json(); + + t.true(response.authorized); + t.is(response.peerCertificate.subject.CN, 'client'); + t.is(response.peerCertificate.issuer.CN, 'authority'); +}); + +test('invalid client certificate (self-signed)', withCertServer, async (t, server, got) => { + server.get('/', (request, response) => { + const peerCertificate = (request.socket as any).getPeerCertificate(true); + peerCertificate.issuerCertificate = undefined; // Circular structure + + response.json({ + authorized: (request.socket as any).authorized, + peerCertificate + }); }); - t.truthy((await got.secure({})).body); + const createCSR = pify(pem.createCSR); + const createCertificate = pify(pem.createCertificate); + + const clientCSRResult = await createCSR({commonName: 'other-client'}); + const clientResult = await createCertificate({ + csr: clientCSRResult.csr, + clientKey: clientCSRResult.clientKey, + selfSigned: true + }); + // eslint-disable-next-line prefer-destructuring + const clientKey = clientResult.clientKey; + const clientCert = clientResult.certificate; + + const response: any = await got.secure({ + https: { + certificateAuthority: clientCert, + key: clientKey, + certificate: clientCert, + rejectUnauthorized: false + } + }).json(); + + t.is(response.authorized, false); }); + +test('invalid client certificate (other CA)', withCertServer, async (t, server, got) => { + server.get('/', (request, response) => { + const peerCertificate = (request.socket as any).getPeerCertificate(true); + + response.json({ + authorized: (request.socket as any).authorized, + peerCertificate + }); + }); + + const createCSR = pify(pem.createCSR); + const createCertificate = pify(pem.createCertificate); + + const caCSRResult = await createCSR({commonName: 'other-authority'}); + const caResult = await createCertificate({ + csr: caCSRResult.csr, + clientKey: caCSRResult.clientKey, + selfSigned: true + }); + const caKey = caResult.clientKey; + const caCert = caResult.certificate; + + const clientCSRResult = await createCSR({commonName: 'other-client'}); + const clientResult = await createCertificate({ + csr: clientCSRResult.csr, + clientKey: clientCSRResult.clientKey, + serviceKey: caKey, + serviceCertificate: caCert + }); + // eslint-disable-next-line prefer-destructuring + const clientKey = clientResult.clientKey; + const clientCert = clientResult.certificate; + + const response: any = await got.secure({ + https: { + certificateAuthority: caCert, + key: clientKey, + certificate: clientCert, + rejectUnauthorized: false + } + }).json(); + + t.false(response.authorized); + t.is(response.peerCertificate.subject.CN, 'other-client'); + t.is(response.peerCertificate.issuer.CN, 'other-authority'); +}); \ No newline at end of file From 1eee9f57dcb6ba24ec65837c31ada95d9217356a Mon Sep 17 00:00:00 2001 From: Giovanni Minotti Date: Mon, 31 Aug 2020 14:54:23 +0200 Subject: [PATCH 04/12] Newline... --- test/https.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/https.ts b/test/https.ts index 50542762d..77c2ce568 100644 --- a/test/https.ts +++ b/test/https.ts @@ -328,4 +328,4 @@ test('invalid client certificate (other CA)', withCertServer, async (t, server, t.false(response.authorized); t.is(response.peerCertificate.subject.CN, 'other-client'); t.is(response.peerCertificate.issuer.CN, 'other-authority'); -}); \ No newline at end of file +}); From ca8d81314ac93bacd5e0c1da207210adf4e85a4a Mon Sep 17 00:00:00 2001 From: Giovanni Minotti Date: Mon, 31 Aug 2020 15:10:43 +0200 Subject: [PATCH 05/12] Small clarifications --- test/https.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/test/https.ts b/test/https.ts index 77c2ce568..292d67078 100644 --- a/test/https.ts +++ b/test/https.ts @@ -232,7 +232,7 @@ test.serial('no double deprecated warning', withServer, async (t, server, got) = test('client certificate', withCertServer, async (t, server, got) => { server.get('/', (request, response) => { const peerCertificate = (request.socket as any).getPeerCertificate(true); - peerCertificate.issuerCertificate = undefined; // Circular structure + peerCertificate.issuerCertificate.issuerCertificate = undefined; // Circular structure response.json({ authorized: (request.socket as any).authorized, @@ -273,10 +273,8 @@ test('invalid client certificate (self-signed)', withCertServer, async (t, serve const response: any = await got.secure({ https: { - certificateAuthority: clientCert, key: clientKey, - certificate: clientCert, - rejectUnauthorized: false + certificate: clientCert } }).json(); @@ -318,10 +316,8 @@ test('invalid client certificate (other CA)', withCertServer, async (t, server, const response: any = await got.secure({ https: { - certificateAuthority: caCert, key: clientKey, - certificate: clientCert, - rejectUnauthorized: false + certificate: clientCert } }).json(); From 6c4d04190f6aaa70653c8ae15a098a1464b7325a Mon Sep 17 00:00:00 2001 From: Giovanni Minotti Date: Mon, 31 Aug 2020 16:03:01 +0200 Subject: [PATCH 06/12] Test for key passphrase --- test/helpers/create-cert-test-server.ts | 14 +-- test/helpers/with-server.ts | 2 - test/https.ts | 112 ++++++++++++++++++++++-- 3 files changed, 106 insertions(+), 22 deletions(-) diff --git a/test/helpers/create-cert-test-server.ts b/test/helpers/create-cert-test-server.ts index f73fd55a7..f70700c2e 100644 --- a/test/helpers/create-cert-test-server.ts +++ b/test/helpers/create-cert-test-server.ts @@ -26,17 +26,6 @@ const createCertTestServer = async () => { const serverKey = serverResult.clientKey; const serverCert = serverResult.certificate; - const clientCSRResult = await createCSR({commonName: 'client'}); - const clientResult = await createCertificate({ - csr: clientCSRResult.csr, - clientKey: clientCSRResult.clientKey, - serviceKey: caKey, - serviceCertificate: caCert - }); - // eslint-disable-next-line prefer-destructuring - const clientKey = clientResult.clientKey; - const clientCert = clientResult.certificate; - const server = express(); (server as any).https = https.createServer( { @@ -53,9 +42,8 @@ const createCertTestServer = async () => { await pify((server as any).https.listen.bind((server as any).https))(); + (server as any).caKey = caKey; (server as any).caCert = caCert; - (server as any).clientCert = clientCert; - (server as any).clientKey = clientKey; (server as any).sslPort = (server as any).https.address().port; (server as any).sslUrl = `https://localhost:${((server as any).sslPort as number)}`; diff --git a/test/helpers/with-server.ts b/test/helpers/with-server.ts index e1f822bcc..a4dca5daf 100644 --- a/test/helpers/with-server.ts +++ b/test/helpers/with-server.ts @@ -46,8 +46,6 @@ const generateHook = ({install, selfSigned, options: testServerOptions}: {instal if (selfSigned) { preparedGot.secure = got.extend({prefixUrl: server.sslUrl, https: { certificateAuthority: (server as any).caCert, - key: (server as any).clientKey, - certificate: (server as any).clientCert, rejectUnauthorized: true }, ...options}); } else { diff --git a/test/https.ts b/test/https.ts index 292d67078..071008027 100644 --- a/test/https.ts +++ b/test/https.ts @@ -6,6 +6,10 @@ import pEvent from 'p-event'; import pify = require('pify'); import pem = require('pem'); +const createPrivateKey = pify(pem.createPrivateKey); +const createCSR = pify(pem.createCSR); +const createCertificate = pify(pem.createCertificate); + test('https request without ca', withServer, async (t, server, got) => { server.get('/', (_request, response) => { response.end('ok'); @@ -240,7 +244,23 @@ test('client certificate', withCertServer, async (t, server, got) => { }); }); - const response: any = await got.secure({}).json(); + const clientCSRResult = await createCSR({commonName: 'client'}); + const clientResult = await createCertificate({ + csr: clientCSRResult.csr, + clientKey: clientCSRResult.clientKey, + serviceKey: (server as any).caKey, + serviceCertificate: (server as any).caCert + }); + // eslint-disable-next-line prefer-destructuring + const clientKey = clientResult.clientKey; + const clientCert = clientResult.certificate; + + const response: any = await got.secure({ + https: { + key: clientKey, + certificate: clientCert + } + }).json(); t.true(response.authorized); t.is(response.peerCertificate.subject.CN, 'client'); @@ -258,9 +278,6 @@ test('invalid client certificate (self-signed)', withCertServer, async (t, serve }); }); - const createCSR = pify(pem.createCSR); - const createCertificate = pify(pem.createCertificate); - const clientCSRResult = await createCSR({commonName: 'other-client'}); const clientResult = await createCertificate({ csr: clientCSRResult.csr, @@ -291,9 +308,6 @@ test('invalid client certificate (other CA)', withCertServer, async (t, server, }); }); - const createCSR = pify(pem.createCSR); - const createCertificate = pify(pem.createCertificate); - const caCSRResult = await createCSR({commonName: 'other-authority'}); const caResult = await createCertificate({ csr: caCSRResult.csr, @@ -325,3 +339,87 @@ test('invalid client certificate (other CA)', withCertServer, async (t, server, t.is(response.peerCertificate.subject.CN, 'other-client'); t.is(response.peerCertificate.issuer.CN, 'other-authority'); }); + +test('key passphrase', withCertServer, async (t, server, got) => { + server.get('/', (request, response) => { + const peerCertificate = (request.socket as any).getPeerCertificate(true); + peerCertificate.issuerCertificate.issuerCertificate = undefined; // Circular structure + + response.json({ + authorized: (request.socket as any).authorized, + peerCertificate + }); + }); + + const {key: clientKey} = await createPrivateKey(2048, { + cipher: 'aes256', + password: 'randomPassword' + }); + const clientCSRResult = await createCSR({ + // eslint-disable-next-line object-shorthand + clientKey: clientKey, + clientKeyPassword: 'randomPassword', + commonName: 'client' + }); + const clientResult = await createCertificate({ + csr: clientCSRResult.csr, + clientKey: clientCSRResult.clientKey, + clientKeyPassword: 'randomPassword', + serviceKey: (server as any).caKey, + serviceCertificate: (server as any).caCert + }); + const clientCert = clientResult.certificate; + + const response: any = await got.secure({ + https: { + key: clientKey, + passphrase: 'randomPassword', + certificate: clientCert + } + }).json(); + + t.true(response.authorized); + t.is(response.peerCertificate.subject.CN, 'client'); + t.is(response.peerCertificate.issuer.CN, 'authority'); +}); + +test('invalid key passphrase', withCertServer, async (t, server, got) => { + server.get('/', (request, response) => { + const peerCertificate = (request.socket as any).getPeerCertificate(true); + peerCertificate.issuerCertificate.issuerCertificate = undefined; // Circular structure + + response.json({ + authorized: (request.socket as any).authorized, + peerCertificate + }); + }); + + const {key: clientKey} = await createPrivateKey(2048, { + cipher: 'aes256', + password: 'randomPassword' + }); + const clientCSRResult = await createCSR({ + // eslint-disable-next-line object-shorthand + clientKey: clientKey, + clientKeyPassword: 'randomPassword', + commonName: 'client' + }); + const clientResult = await createCertificate({ + csr: clientCSRResult.csr, + clientKey: clientCSRResult.clientKey, + clientKeyPassword: 'randomPassword', + serviceKey: (server as any).caKey, + serviceCertificate: (server as any).caCert + }); + const clientCert = clientResult.certificate; + + await t.throwsAsync(got.secure({ + https: { + key: clientKey, + passphrase: 'wrongPassword', + certificate: clientCert + } + }), { + code: 'ERR_OSSL_EVP_BAD_DECRYPT' + }); +}); From 29e4c0263710ed7eb76c69b97ff6789c2c373718 Mon Sep 17 00:00:00 2001 From: Giovanni Minotti Date: Mon, 31 Aug 2020 16:11:32 +0200 Subject: [PATCH 07/12] Fixed test for Node.JS 10 --- test/https.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/test/https.ts b/test/https.ts index 071008027..aa05d7ea7 100644 --- a/test/https.ts +++ b/test/https.ts @@ -413,13 +413,26 @@ test('invalid key passphrase', withCertServer, async (t, server, got) => { }); const clientCert = clientResult.certificate; - await t.throwsAsync(got.secure({ + const NODE_10 = process.versions.node.split('.')[0] === '10'; + + const request = got.secure({ https: { key: clientKey, passphrase: 'wrongPassword', certificate: clientCert } - }), { - code: 'ERR_OSSL_EVP_BAD_DECRYPT' }); + + // Node.JS 10 does not have an error code, it only has a mesage + if (NODE_10) { + try { + await request; + } catch (error) { + t.true((error.message as string).includes('bad decrypt')); + } + } else { + await t.throwsAsync(request, { + code: 'ERR_OSSL_EVP_BAD_DECRYPT' + }); + } }); From 13fcbdc6c75c1e2e19f64d9e3a27fbab8fde243e Mon Sep 17 00:00:00 2001 From: Giovanni Minotti Date: Mon, 31 Aug 2020 16:26:36 +0200 Subject: [PATCH 08/12] Added PFX test environment --- test/https.ts | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/https.ts b/test/https.ts index aa05d7ea7..47006af8b 100644 --- a/test/https.ts +++ b/test/https.ts @@ -9,6 +9,7 @@ import pem = require('pem'); const createPrivateKey = pify(pem.createPrivateKey); const createCSR = pify(pem.createCSR); const createCertificate = pify(pem.createCertificate); +const createPkcs12 = pify(pem.createPkcs12); test('https request without ca', withServer, async (t, server, got) => { server.get('/', (_request, response) => { @@ -436,3 +437,38 @@ test('invalid key passphrase', withCertServer, async (t, server, got) => { }); } }); + +test('client certificate PFX', withCertServer, async (t, server, got) => { + server.get('/', (request, response) => { + const peerCertificate = (request.socket as any).getPeerCertificate(true); + peerCertificate.issuerCertificate = undefined; // Circular structure + + response.json({ + authorized: (request.socket as any).authorized, + peerCertificate + }); + }); + + const clientCSRResult = await createCSR({commonName: 'client'}); + const clientResult = await createCertificate({ + csr: clientCSRResult.csr, + clientKey: clientCSRResult.clientKey, + serviceKey: (server as any).caKey, + serviceCertificate: (server as any).caCert + }); + // eslint-disable-next-line prefer-destructuring + const clientKey = clientResult.clientKey; + const clientCert = clientResult.certificate; + + const {pkcs12} = await createPkcs12(clientKey, clientCert, 'randomPassword'); + + // Change me on PR #1364 + const response: any = await got.secure({ + pfx: pkcs12, + passphrase: 'randomPassword' + } as any).json(); + + t.true(response.authorized); + t.is(response.peerCertificate.subject.CN, 'client'); + t.is(response.peerCertificate.issuer.CN, 'authority'); +}); From bc6ee75cbde4fee1111efe9f1751590edb70435e Mon Sep 17 00:00:00 2001 From: Giovanni Minotti Date: Mon, 31 Aug 2020 21:48:59 +0200 Subject: [PATCH 09/12] Wrote all the HTTPS tests with the new server helper --- ...-server.ts => create-https-test-server.ts} | 18 ++-- test/helpers/with-server.ts | 41 +++++--- test/https.ts | 98 ++++++++----------- 3 files changed, 83 insertions(+), 74 deletions(-) rename test/helpers/{create-cert-test-server.ts => create-https-test-server.ts} (72%) diff --git a/test/helpers/create-cert-test-server.ts b/test/helpers/create-https-test-server.ts similarity index 72% rename from test/helpers/create-cert-test-server.ts rename to test/helpers/create-https-test-server.ts index f70700c2e..a6129c4bf 100644 --- a/test/helpers/create-cert-test-server.ts +++ b/test/helpers/create-https-test-server.ts @@ -3,7 +3,12 @@ import express = require('express'); import pify = require('pify'); import pem = require('pem'); -const createCertTestServer = async () => { +export type HttpsServerOptions = { + commonName?: string; + days?: number; +}; + +const createHttpsTestServer = async (options: HttpsServerOptions = {}) => { const createCSR = pify(pem.createCSR); const createCertificate = pify(pem.createCertificate); @@ -16,12 +21,13 @@ const createCertTestServer = async () => { const caKey = caResult.clientKey; const caCert = caResult.certificate; - const serverCSRResult = await createCSR({commonName: 'localhost'}); + const serverCSRResult = await createCSR({commonName: options.commonName ?? 'localhost'}); const serverResult = await createCertificate({ csr: serverCSRResult.csr, clientKey: serverCSRResult.clientKey, serviceKey: caKey, - serviceCertificate: caCert + serviceCertificate: caCert, + days: options.days ?? 365 }); const serverKey = serverResult.clientKey; const serverCert = serverResult.certificate; @@ -44,8 +50,8 @@ const createCertTestServer = async () => { (server as any).caKey = caKey; (server as any).caCert = caCert; - (server as any).sslPort = (server as any).https.address().port; - (server as any).sslUrl = `https://localhost:${((server as any).sslPort as number)}`; + (server as any).port = (server as any).https.address().port; + (server as any).url = `https://localhost:${((server as any).port as number)}`; (server as any).close = () => pify((server as any).https.close.bind((server as any).https))(); @@ -53,4 +59,4 @@ const createCertTestServer = async () => { return server; }; -export default createCertTestServer; +export default createHttpsTestServer; diff --git a/test/helpers/with-server.ts b/test/helpers/with-server.ts index a4dca5daf..86449ac65 100644 --- a/test/helpers/with-server.ts +++ b/test/helpers/with-server.ts @@ -3,20 +3,21 @@ import * as test from 'ava'; import is from '@sindresorhus/is'; import http = require('http'); import tempy = require('tempy'); -import createCertTestServer from './create-cert-test-server'; +import createHttpsTestServer, {HttpsServerOptions} from './create-https-test-server'; import createTestServer = require('create-test-server'); import FakeTimers = require('@sinonjs/fake-timers'); import got, {InstanceDefaults} from '../../source'; import {ExtendedGot, ExtendedHttpServer, ExtendedTestServer, GlobalClock, InstalledClock} from './types'; export type RunTestWithServer = (t: test.ExecutionContext, server: ExtendedTestServer, got: ExtendedGot, clock: GlobalClock) => Promise | void; +export type RunTestWithHttpsServer = (t: test.ExecutionContext, server: ExtendedTestServer, got: ExtendedGot) => Promise | void; export type RunTestWithSocket = (t: test.ExecutionContext, server: ExtendedHttpServer) => Promise | void; -const generateHook = ({install, selfSigned, options: testServerOptions}: {install?: boolean; selfSigned?: boolean; options?: unknown}): test.Macro<[RunTestWithServer]> => async (t, run) => { +const generateHook = ({install, options: testServerOptions}: {install?: boolean; options?: unknown}): test.Macro<[RunTestWithServer]> => async (t, run) => { const clock = install ? FakeTimers.install() : FakeTimers.createClock() as GlobalClock; // Re-enable body parsing to investigate https://github.com/sindresorhus/got/issues/1186 - const server = await (selfSigned ? createCertTestServer : createTestServer)(is.plainObject(testServerOptions) ? testServerOptions : { + const server = await createTestServer(is.plainObject(testServerOptions) ? testServerOptions : { bodyParser: { type: () => false }, @@ -43,15 +44,8 @@ const generateHook = ({install, selfSigned, options: testServerOptions}: {instal }; const preparedGot = got.extend({prefixUrl: server.url, ...options}) as ExtendedGot; - if (selfSigned) { - preparedGot.secure = got.extend({prefixUrl: server.sslUrl, https: { - certificateAuthority: (server as any).caCert, - rejectUnauthorized: true - }, ...options}); - } else { - preparedGot.secure = got.extend({prefixUrl: server.sslUrl, ...options}); - server.hostname = (new URL(server.url)).hostname; - } + preparedGot.secure = got.extend({prefixUrl: server.sslUrl, ...options}); + server.hostname = (new URL(server.url)).hostname; server.sslHostname = (new URL(server.sslUrl)).hostname; @@ -67,11 +61,32 @@ const generateHook = ({install, selfSigned, options: testServerOptions}: {instal }; export const withBodyParsingServer = generateHook({install: false, options: {}}); -export const withCertServer = generateHook({install: false, selfSigned: true, options: {}}); export default generateHook({install: false}); export const withServerAndFakeTimers = generateHook({install: true}); +const generateHttpsHook = (options?: HttpsServerOptions): test.Macro<[RunTestWithHttpsServer]> => async (t, run) => { + const server = await createHttpsTestServer(options) as ExtendedTestServer; + + const preparedGot = got.extend({ + // @ts-expect-error Augmenting for test detection + avaTest: t.title, + prefixUrl: server.url, + https: { + certificateAuthority: (server as any).caCert, + rejectUnauthorized: true + } + }) as ExtendedGot; + + try { + await run(t, server, preparedGot); + } finally { + await server.close(); + } +}; + +export const withHttpsServer = generateHttpsHook; + // TODO: remove this when `create-test-server` supports custom listen export const withSocketServer: test.Macro<[RunTestWithSocket]> = async (t, run) => { const socketPath = tempy.file({extension: 'socket'}); diff --git a/test/https.ts b/test/https.ts index 47006af8b..f7900cc7c 100644 --- a/test/https.ts +++ b/test/https.ts @@ -1,6 +1,6 @@ import test from 'ava'; import got, {CancelableRequest} from '../source'; -import withServer, {withCertServer} from './helpers/with-server'; +import {withHttpsServer} from './helpers/with-server'; import {DetailedPeerCertificate} from 'tls'; import pEvent from 'p-event'; import pify = require('pify'); @@ -11,34 +11,30 @@ const createCSR = pify(pem.createCSR); const createCertificate = pify(pem.createCertificate); const createPkcs12 = pify(pem.createPkcs12); -test('https request without ca', withServer, async (t, server, got) => { +test('https request without ca', withHttpsServer(), async (t, server, got) => { server.get('/', (_request, response) => { response.end('ok'); }); - t.truthy((await got.secure({ + t.truthy((await got({ https: { + certificateAuthority: [], rejectUnauthorized: false } })).body); }); -test('https request with ca', withServer, async (t, server, got) => { +test('https request with ca', withHttpsServer(), async (t, server, got) => { server.get('/', (_request, response) => { response.end('ok'); }); - const {body} = await got.secure({ - https: { - certificateAuthority: server.caCert - }, - headers: {host: 'example.com'} - }); + const {body} = await got({}); t.is(body, 'ok'); }); -test('https request with ca and afterResponse hook', withServer, async (t, server, got) => { +test('https request with ca and afterResponse hook', withHttpsServer(), async (t, server, got) => { server.get('/', (_request, response) => { response.end('ok'); }); @@ -57,11 +53,7 @@ test('https request with ca and afterResponse hook', withServer, async (t, serve process.once('warning', warningListener); let shouldRetry = true; - const {body} = await got.secure({ - https: { - certificateAuthority: server.caCert - }, - headers: {host: 'example.com'}, + const {body} = await got({ hooks: { afterResponse: [ (response, retry) => { @@ -80,43 +72,39 @@ test('https request with ca and afterResponse hook', withServer, async (t, serve t.is(body, 'ok'); }); -test('https request with `checkServerIdentity` OK', withServer, async (t, server, got) => { +test('https request with `checkServerIdentity` OK', withHttpsServer(), async (t, server, got) => { server.get('/', (_request, response) => { response.end('ok'); }); - const {body} = await got.secure({ + const {body} = await got({ https: { - certificateAuthority: server.caCert, checkServerIdentity: (hostname: string, certificate: DetailedPeerCertificate) => { - t.is(hostname, 'example.com'); - t.is(certificate.subject.CN, 'example.com'); - t.is(certificate.issuer.CN, 'localhost'); + t.is(hostname, 'localhost'); + t.is(certificate.subject.CN, 'localhost'); + t.is(certificate.issuer.CN, 'authority'); } - }, - headers: {host: 'example.com'} + } }); t.is(body, 'ok'); }); -test('https request with `checkServerIdentity` NOT OK', withServer, async (t, server, got) => { +test('https request with `checkServerIdentity` NOT OK', withHttpsServer(), async (t, server, got) => { server.get('/', (_request, response) => { response.end('ok'); }); - const promise = got.secure({ + const promise = got({ https: { - certificateAuthority: server.caCert, checkServerIdentity: (hostname: string, certificate: DetailedPeerCertificate) => { - t.is(hostname, 'example.com'); - t.is(certificate.subject.CN, 'example.com'); - t.is(certificate.issuer.CN, 'localhost'); + t.is(hostname, 'localhost'); + t.is(certificate.subject.CN, 'localhost'); + t.is(certificate.issuer.CN, 'authority'); return new Error('CUSTOM_ERROR'); } - }, - headers: {host: 'example.com'} + } }); await t.throwsAsync( @@ -127,18 +115,18 @@ test('https request with `checkServerIdentity` NOT OK', withServer, async (t, se ); }); -test('https request with expired certificate', async t => { +test('https request with expired certificate', withHttpsServer({days: -1}), async (t, _server, got) => { await t.throwsAsync( - got('https://expired.badssl.com/'), + got({}), { code: 'CERT_HAS_EXPIRED' } ); }); -test('https request with wrong host', async t => { +test('https request with wrong host', withHttpsServer({commonName: 'not-localhost.com'}), async (t, _server, got) => { await t.throwsAsync( - got('https://wrong.host.badssl.com/'), + got({}), { code: 'ERR_TLS_CERT_ALTNAME_INVALID' } @@ -158,7 +146,7 @@ test('http2', async t => { t.is(typeof body, 'string'); }); -test.serial('deprecated `rejectUnauthorized` option', withServer, async (t, server, got) => { +test.serial('deprecated `rejectUnauthorized` option', withHttpsServer(), async (t, server, got) => { server.get('/', (_request, response) => { response.end('ok'); }); @@ -173,7 +161,7 @@ test.serial('deprecated `rejectUnauthorized` option', withServer, async (t, serv })(); (async () => { - request = got.secure({ + request = got({ rejectUnauthorized: false }); @@ -189,7 +177,7 @@ test.serial('deprecated `rejectUnauthorized` option', withServer, async (t, serv }); }); -test.serial('non-deprecated `rejectUnauthorized` option', withServer, async (t, server, got) => { +test.serial('non-deprecated `rejectUnauthorized` option', withHttpsServer(), async (t, server, got) => { server.get('/', (_request, response) => { response.end('ok'); }); @@ -199,7 +187,7 @@ test.serial('non-deprecated `rejectUnauthorized` option', withServer, async (t, t.not(warning.name, 'DeprecationWarning'); })(); - await got.secure({ + await got({ https: { rejectUnauthorized: false } @@ -208,7 +196,7 @@ test.serial('non-deprecated `rejectUnauthorized` option', withServer, async (t, t.pass(); }); -test.serial('no double deprecated warning', withServer, async (t, server, got) => { +test.serial('no double deprecated warning', withHttpsServer(), async (t, server, got) => { server.get('/', (_request, response) => { response.end('ok'); }); @@ -218,7 +206,7 @@ test.serial('no double deprecated warning', withServer, async (t, server, got) = t.is(warning.name, 'DeprecationWarning'); })(); - await got.secure({ + await got({ rejectUnauthorized: false }); @@ -227,14 +215,14 @@ test.serial('no double deprecated warning', withServer, async (t, server, got) = t.not(warning.name, 'DeprecationWarning'); })(); - await got.secure({ + await got({ rejectUnauthorized: false }); t.pass(); }); -test('client certificate', withCertServer, async (t, server, got) => { +test('client certificate', withHttpsServer(), async (t, server, got) => { server.get('/', (request, response) => { const peerCertificate = (request.socket as any).getPeerCertificate(true); peerCertificate.issuerCertificate.issuerCertificate = undefined; // Circular structure @@ -256,7 +244,7 @@ test('client certificate', withCertServer, async (t, server, got) => { const clientKey = clientResult.clientKey; const clientCert = clientResult.certificate; - const response: any = await got.secure({ + const response: any = await got({ https: { key: clientKey, certificate: clientCert @@ -268,7 +256,7 @@ test('client certificate', withCertServer, async (t, server, got) => { t.is(response.peerCertificate.issuer.CN, 'authority'); }); -test('invalid client certificate (self-signed)', withCertServer, async (t, server, got) => { +test('invalid client certificate (self-signed)', withHttpsServer(), async (t, server, got) => { server.get('/', (request, response) => { const peerCertificate = (request.socket as any).getPeerCertificate(true); peerCertificate.issuerCertificate = undefined; // Circular structure @@ -289,7 +277,7 @@ test('invalid client certificate (self-signed)', withCertServer, async (t, serve const clientKey = clientResult.clientKey; const clientCert = clientResult.certificate; - const response: any = await got.secure({ + const response: any = await got({ https: { key: clientKey, certificate: clientCert @@ -299,7 +287,7 @@ test('invalid client certificate (self-signed)', withCertServer, async (t, serve t.is(response.authorized, false); }); -test('invalid client certificate (other CA)', withCertServer, async (t, server, got) => { +test('invalid client certificate (other CA)', withHttpsServer(), async (t, server, got) => { server.get('/', (request, response) => { const peerCertificate = (request.socket as any).getPeerCertificate(true); @@ -329,7 +317,7 @@ test('invalid client certificate (other CA)', withCertServer, async (t, server, const clientKey = clientResult.clientKey; const clientCert = clientResult.certificate; - const response: any = await got.secure({ + const response: any = await got({ https: { key: clientKey, certificate: clientCert @@ -341,7 +329,7 @@ test('invalid client certificate (other CA)', withCertServer, async (t, server, t.is(response.peerCertificate.issuer.CN, 'other-authority'); }); -test('key passphrase', withCertServer, async (t, server, got) => { +test('key passphrase', withHttpsServer(), async (t, server, got) => { server.get('/', (request, response) => { const peerCertificate = (request.socket as any).getPeerCertificate(true); peerCertificate.issuerCertificate.issuerCertificate = undefined; // Circular structure @@ -371,7 +359,7 @@ test('key passphrase', withCertServer, async (t, server, got) => { }); const clientCert = clientResult.certificate; - const response: any = await got.secure({ + const response: any = await got({ https: { key: clientKey, passphrase: 'randomPassword', @@ -384,7 +372,7 @@ test('key passphrase', withCertServer, async (t, server, got) => { t.is(response.peerCertificate.issuer.CN, 'authority'); }); -test('invalid key passphrase', withCertServer, async (t, server, got) => { +test('invalid key passphrase', withHttpsServer(), async (t, server, got) => { server.get('/', (request, response) => { const peerCertificate = (request.socket as any).getPeerCertificate(true); peerCertificate.issuerCertificate.issuerCertificate = undefined; // Circular structure @@ -416,7 +404,7 @@ test('invalid key passphrase', withCertServer, async (t, server, got) => { const NODE_10 = process.versions.node.split('.')[0] === '10'; - const request = got.secure({ + const request = got({ https: { key: clientKey, passphrase: 'wrongPassword', @@ -438,7 +426,7 @@ test('invalid key passphrase', withCertServer, async (t, server, got) => { } }); -test('client certificate PFX', withCertServer, async (t, server, got) => { +test('client certificate PFX', withHttpsServer(), async (t, server, got) => { server.get('/', (request, response) => { const peerCertificate = (request.socket as any).getPeerCertificate(true); peerCertificate.issuerCertificate = undefined; // Circular structure @@ -463,7 +451,7 @@ test('client certificate PFX', withCertServer, async (t, server, got) => { const {pkcs12} = await createPkcs12(clientKey, clientCert, 'randomPassword'); // Change me on PR #1364 - const response: any = await got.secure({ + const response: any = await got({ pfx: pkcs12, passphrase: 'randomPassword' } as any).json(); From 88cab11b52b1668873907617b58f73399e040fd4 Mon Sep 17 00:00:00 2001 From: Giovanni Minotti Date: Mon, 31 Aug 2020 21:55:01 +0200 Subject: [PATCH 10/12] Fixed types --- test/helpers/create-https-test-server.ts | 28 ++++++++++++++++-------- test/helpers/with-server.ts | 6 ++--- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/test/helpers/create-https-test-server.ts b/test/helpers/create-https-test-server.ts index a6129c4bf..df003cd35 100644 --- a/test/helpers/create-https-test-server.ts +++ b/test/helpers/create-https-test-server.ts @@ -1,4 +1,5 @@ import https = require('https'); +import net = require('net'); import express = require('express'); import pify = require('pify'); import pem = require('pem'); @@ -8,6 +9,15 @@ export type HttpsServerOptions = { days?: number; }; +export interface ExtendedHttpsTestServer extends express.Express { + https: https.Server, + caKey: Buffer, + caCert: Buffer, + url: string, + port: number, + close: () => any +} + const createHttpsTestServer = async (options: HttpsServerOptions = {}) => { const createCSR = pify(pem.createCSR); const createCertificate = pify(pem.createCertificate); @@ -32,8 +42,8 @@ const createHttpsTestServer = async (options: HttpsServerOptions = {}) => { const serverKey = serverResult.clientKey; const serverCert = serverResult.certificate; - const server = express(); - (server as any).https = https.createServer( + const server = express() as ExtendedHttpsTestServer; + server.https = https.createServer( { key: serverKey, cert: serverCert, @@ -46,15 +56,15 @@ const createHttpsTestServer = async (options: HttpsServerOptions = {}) => { server.set('etag', false); - await pify((server as any).https.listen.bind((server as any).https))(); + await pify(server.https.listen.bind(server.https))(); - (server as any).caKey = caKey; - (server as any).caCert = caCert; - (server as any).port = (server as any).https.address().port; - (server as any).url = `https://localhost:${((server as any).port as number)}`; + server.caKey = caKey; + server.caCert = caCert; + server.port = (server.https.address() as net.AddressInfo).port; + server.url = `https://localhost:${(server.port as number)}`; - (server as any).close = () => - pify((server as any).https.close.bind((server as any).https))(); + server.close = () => + pify(server.https.close.bind(server.https))(); return server; }; diff --git a/test/helpers/with-server.ts b/test/helpers/with-server.ts index 86449ac65..559525fdc 100644 --- a/test/helpers/with-server.ts +++ b/test/helpers/with-server.ts @@ -3,14 +3,14 @@ import * as test from 'ava'; import is from '@sindresorhus/is'; import http = require('http'); import tempy = require('tempy'); -import createHttpsTestServer, {HttpsServerOptions} from './create-https-test-server'; +import createHttpsTestServer, {ExtendedHttpsTestServer, HttpsServerOptions} from './create-https-test-server'; import createTestServer = require('create-test-server'); import FakeTimers = require('@sinonjs/fake-timers'); import got, {InstanceDefaults} from '../../source'; import {ExtendedGot, ExtendedHttpServer, ExtendedTestServer, GlobalClock, InstalledClock} from './types'; export type RunTestWithServer = (t: test.ExecutionContext, server: ExtendedTestServer, got: ExtendedGot, clock: GlobalClock) => Promise | void; -export type RunTestWithHttpsServer = (t: test.ExecutionContext, server: ExtendedTestServer, got: ExtendedGot) => Promise | void; +export type RunTestWithHttpsServer = (t: test.ExecutionContext, server: ExtendedHttpsTestServer, got: ExtendedGot) => Promise | void; export type RunTestWithSocket = (t: test.ExecutionContext, server: ExtendedHttpServer) => Promise | void; const generateHook = ({install, options: testServerOptions}: {install?: boolean; options?: unknown}): test.Macro<[RunTestWithServer]> => async (t, run) => { @@ -66,7 +66,7 @@ export default generateHook({install: false}); export const withServerAndFakeTimers = generateHook({install: true}); const generateHttpsHook = (options?: HttpsServerOptions): test.Macro<[RunTestWithHttpsServer]> => async (t, run) => { - const server = await createHttpsTestServer(options) as ExtendedTestServer; + const server = await createHttpsTestServer(options) as ExtendedHttpsTestServer; const preparedGot = got.extend({ // @ts-expect-error Augmenting for test detection From c308bfbe409199a395afc0a26b0f8ad4cc455ad9 Mon Sep 17 00:00:00 2001 From: Giovanni Minotti Date: Mon, 31 Aug 2020 22:00:30 +0200 Subject: [PATCH 11/12] Linting... --- test/helpers/create-https-test-server.ts | 18 +++++++++--------- test/helpers/with-server.ts | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/helpers/create-https-test-server.ts b/test/helpers/create-https-test-server.ts index df003cd35..77d4e5602 100644 --- a/test/helpers/create-https-test-server.ts +++ b/test/helpers/create-https-test-server.ts @@ -10,15 +10,15 @@ export type HttpsServerOptions = { }; export interface ExtendedHttpsTestServer extends express.Express { - https: https.Server, - caKey: Buffer, - caCert: Buffer, - url: string, - port: number, - close: () => any + https: https.Server; + caKey: Buffer; + caCert: Buffer; + url: string; + port: number; + close: () => Promise; } -const createHttpsTestServer = async (options: HttpsServerOptions = {}) => { +const createHttpsTestServer = async (options: HttpsServerOptions = {}): Promise => { const createCSR = pify(pem.createCSR); const createCertificate = pify(pem.createCertificate); @@ -61,9 +61,9 @@ const createHttpsTestServer = async (options: HttpsServerOptions = {}) => { server.caKey = caKey; server.caCert = caCert; server.port = (server.https.address() as net.AddressInfo).port; - server.url = `https://localhost:${(server.port as number)}`; + server.url = `https://localhost:${(server.port)}`; - server.close = () => + server.close = async () => pify(server.https.close.bind(server.https))(); return server; diff --git a/test/helpers/with-server.ts b/test/helpers/with-server.ts index 559525fdc..c6e6a4ca8 100644 --- a/test/helpers/with-server.ts +++ b/test/helpers/with-server.ts @@ -66,7 +66,7 @@ export default generateHook({install: false}); export const withServerAndFakeTimers = generateHook({install: true}); const generateHttpsHook = (options?: HttpsServerOptions): test.Macro<[RunTestWithHttpsServer]> => async (t, run) => { - const server = await createHttpsTestServer(options) as ExtendedHttpsTestServer; + const server = await createHttpsTestServer(options); const preparedGot = got.extend({ // @ts-expect-error Augmenting for test detection From fc223796dfc52aab88ce98188398bd0cd5bb81ae Mon Sep 17 00:00:00 2001 From: Giovanni Minotti Date: Tue, 1 Sep 2020 12:47:29 +0200 Subject: [PATCH 12/12] Small fix for "invalid key passphrase" test --- test/https.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/https.ts b/test/https.ts index f7900cc7c..9d69ccb3a 100644 --- a/test/https.ts +++ b/test/https.ts @@ -416,6 +416,7 @@ test('invalid key passphrase', withHttpsServer(), async (t, server, got) => { if (NODE_10) { try { await request; + t.fail(); } catch (error) { t.true((error.message as string).includes('bad decrypt')); }