1- import { execFile } from 'node:child_process'
21/** @vitest -environment node */
3- import { readFileSync } from 'node:fs'
2+ import { execFile } from 'node:child_process'
3+ import { mkdtempSync , readFileSync , rmSync } from 'node:fs'
44import { createServer as httpServer } from 'node:http'
55import { createServer as httpsServer } from 'node:https'
66import { type AddressInfo , connect , type Socket } from 'node:net'
7+ import { tmpdir } from 'node:os'
8+ import { join } from 'node:path'
79import { getCACertificates , setDefaultCACertificates } from 'node:tls'
810import { fileURLToPath } from 'node:url'
911import { promisify } from 'node:util'
@@ -30,8 +32,10 @@ import {
3032 secureFetchWithPinnedIP ,
3133} from '@/lib/core/security/input-validation.server'
3234
33- const cert = readFileSync ( new URL ( './fixtures/gateway-test-cert.pem' , import . meta. url ) , 'utf8' )
34- const key = readFileSync ( new URL ( './fixtures/gateway-test-key.pem' , import . meta. url ) , 'utf8' )
35+ const certificateDirectory = mkdtempSync ( join ( tmpdir ( ) , 'gateway-tls-' ) )
36+ const certificatePath = join ( certificateDirectory , 'cert.pem' )
37+ const keyPath = join ( certificateDirectory , 'key.pem' )
38+ let cert = ''
3539const sockets = new Set < Socket > ( )
3640const admissions : Array < {
3741 token : string | undefined
@@ -54,11 +58,11 @@ const origin = httpServer(async (req, res) => {
5458 res . end ( req . method === 'POST' ? Buffer . concat ( chunks ) : 'reached' )
5559} )
5660const proxiedPorts = new Set < number > ( )
57- const secureOrigin = httpsServer ( { cert , key } , ( req , res ) => {
61+ const secureOrigin = httpsServer ( ( req , res ) => {
5862 res . setHeader ( 'x-via-proxy' , proxiedPorts . has ( req . socket . remotePort ?? 0 ) ? 'yes' : 'no' )
5963 res . end ( 'tls reached' )
6064} )
61- const proxy = httpsServer ( { cert , key } )
65+ const proxy = httpsServer ( )
6266proxy . on ( 'connect' , ( req , socket , head ) => {
6367 socket . on ( 'error' , ( ) => { } )
6468 const tlsSocket = req . socket as Socket & { servername ?: string }
@@ -88,6 +92,29 @@ let originPort = 0
8892let securePort = 0
8993const trust = getCACertificates ( 'default' )
9094beforeAll ( async ( ) => {
95+ await promisify ( execFile ) ( 'openssl' , [
96+ 'req' ,
97+ '-x509' ,
98+ '-newkey' ,
99+ 'rsa:2048' ,
100+ '-sha256' ,
101+ '-nodes' ,
102+ '-keyout' ,
103+ keyPath ,
104+ '-out' ,
105+ certificatePath ,
106+ '-days' ,
107+ '2' ,
108+ '-subj' ,
109+ '/CN=gateway.invalid' ,
110+ '-addext' ,
111+ 'subjectAltName=DNS:gateway.invalid,DNS:localhost' ,
112+ '-addext' ,
113+ 'extendedKeyUsage=serverAuth' ,
114+ ] )
115+ cert = readFileSync ( certificatePath , 'utf8' )
116+ const key = readFileSync ( keyPath , 'utf8' )
117+ for ( const server of [ secureOrigin , proxy ] ) server . setSecureContext ( { cert, key } )
91118 setDefaultCACertificates ( [ ...trust , cert ] )
92119 for ( const server of [ origin , secureOrigin , proxy ] ) {
93120 server . on ( 'connection' , ( socket ) => {
@@ -120,6 +147,7 @@ afterAll(async () => {
120147 )
121148 )
122149 setDefaultCACertificates ( trust )
150+ rmSync ( certificateDirectory , { recursive : true , force : true } )
123151} )
124152const url = ( ) => `http://localhost:${ originPort } `
125153const options = { profile : 'selfHostedService' as const }
@@ -266,14 +294,13 @@ describe('organization gateways over real TLS CONNECT sockets', () => {
266294 fileURLToPath ( new URL ( './fixtures/gateway-runtime.fixture.ts' , import . meta. url ) ) ,
267295 String ( ( proxy . address ( ) as AddressInfo ) . port ) ,
268296 String ( securePort ) ,
297+ certificatePath ,
269298 ] ,
270299 {
271300 timeout : 15_000 ,
272301 env : {
273302 ...process . env ,
274- NODE_EXTRA_CA_CERTS : fileURLToPath (
275- new URL ( './fixtures/gateway-test-cert.pem' , import . meta. url )
276- ) ,
303+ NODE_EXTRA_CA_CERTS : certificatePath ,
277304 OUTBOUND_ROUTING_SOURCE : 'env' ,
278305 OUTBOUND_ROUTING_CONFIG : JSON . stringify ( {
279306 schemaVersion : 1 ,
0 commit comments