Skip to content

Commit a2b89d0

Browse files
committed
fix: raise connection string error early on request processing
1 parent 1d8cfa3 commit a2b89d0

File tree

2 files changed

+35
-18
lines changed

2 files changed

+35
-18
lines changed

src/server/routes/index.ts

+29-14
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,39 @@ import { PG_CONNECTION, CRYPTO_KEY } from '../constants.js'
2626
export default async (fastify: FastifyInstance) => {
2727
// Adds a "pg" object to the request if it doesn't exist
2828
fastify.addHook('onRequest', (request, _reply, done) => {
29-
// Node converts headers to lowercase
30-
const encryptedHeader = request.headers['x-connection-encrypted']?.toString()
31-
if (encryptedHeader) {
29+
try {
30+
// Node converts headers to lowercase
31+
const encryptedHeader = request.headers['x-connection-encrypted']?.toString()
32+
if (encryptedHeader) {
33+
try {
34+
request.headers.pg = CryptoJS.AES.decrypt(encryptedHeader, CRYPTO_KEY)
35+
.toString(CryptoJS.enc.Utf8)
36+
.trim()
37+
} catch (e: any) {
38+
request.log.warn({
39+
message: 'failed to parse encrypted connstring',
40+
error: e.toString(),
41+
})
42+
throw new Error('failed to process upstream connection details')
43+
}
44+
} else {
45+
request.headers.pg = PG_CONNECTION
46+
}
47+
if (!request.headers.pg) {
48+
request.log.error({ message: 'failed to get connection string' })
49+
throw new Error('failed to get upstream connection details')
50+
}
51+
// Ensure the resulting connection string is a valid URL
3252
try {
33-
request.headers.pg = CryptoJS.AES.decrypt(encryptedHeader, CRYPTO_KEY).toString(
34-
CryptoJS.enc.Utf8
35-
)
36-
} catch (e: any) {
37-
request.log.warn({
38-
message: 'failed to parse encrypted connstring',
39-
error: e.toString(),
40-
})
53+
new URL(request.headers.pg)
54+
} catch (error) {
55+
request.log.error({ message: 'pg connection string is invalid url' })
4156
throw new Error('failed to process upstream connection details')
4257
}
43-
} else {
44-
request.headers.pg = PG_CONNECTION
58+
done()
59+
} catch (err) {
60+
return done(err as Error)
4561
}
46-
done()
4762
})
4863

4964
fastify.register(ColumnPrivilegesRoute, { prefix: '/column-privileges' })

test/server/ssl.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,10 @@ test('query with invalid space empty encrypted connection string', async () => {
8282
},
8383
payload: { query: 'select 1;' },
8484
})
85+
expect(res.statusCode).toBe(500)
8586
expect(res.json()).toMatchInlineSnapshot(`
8687
{
87-
"error": "Invalid URL",
88+
"error": "failed to get upstream connection details",
8889
}
8990
`)
9091
})
@@ -98,10 +99,10 @@ test('query with invalid empty encrypted connection string', async () => {
9899
},
99100
payload: { query: 'select 1;' },
100101
})
102+
expect(res.statusCode).toBe(500)
101103
expect(res.json()).toMatchInlineSnapshot(`
102104
{
103-
"error": "SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string",
104-
"message": "SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string",
105+
"error": "failed to get upstream connection details",
105106
}
106107
`)
107108
})
@@ -118,9 +119,10 @@ test('query with missing host connection string encrypted connection string', as
118119
},
119120
payload: { query: 'select 1;' },
120121
})
122+
expect(res.statusCode).toBe(500)
121123
expect(res.json()).toMatchInlineSnapshot(`
122124
{
123-
"error": "Invalid URL",
125+
"error": "failed to process upstream connection details",
124126
}
125127
`)
126128
})

0 commit comments

Comments
 (0)