Skip to content

Commit

Permalink
feat: allow setting ssl root cert
Browse files Browse the repository at this point in the history
  • Loading branch information
soedirgo committed Aug 21, 2023
1 parent 7e7d114 commit 3514106
Show file tree
Hide file tree
Showing 9 changed files with 922 additions and 690 deletions.
1,388 changes: 717 additions & 671 deletions package-lock.json

Large diffs are not rendered by default.

19 changes: 10 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,28 +56,29 @@
]
},
"dependencies": {
"@sinclair/typebox": "^0.25.1",
"pg": "^8.7.1",
"pg-format": "^1.0.4",
"pgsql-parser": "^13.3.0",
"postgres-array": "^3.0.1",
"prettier": "^2.6.0",
"prettier-plugin-sql": "^0.13.0",
"pino": "^8.6.1",
"@fastify/cors": "^8.2.0",
"@fastify/swagger": "^8.2.1",
"@fastify/type-provider-typebox": "^2.4.0",
"@sinclair/typebox": "^0.25.1",
"crypto-js": "^4.0.0",
"fastify": "^4.8.1",
"fastify-metrics": "^10.0.0",
"pg-connection-string": "^2.5.0"
"pg": "^8.7.1",
"pg-connection-string": "^2.5.0",
"pg-format": "^1.0.4",
"pgsql-parser": "^13.3.0",
"pino": "^8.6.1",
"postgres-array": "^3.0.1",
"prettier": "^2.6.0",
"prettier-plugin-sql": "^0.13.0"
},
"devDependencies": {
"@types/crypto-js": "^4.1.1",
"@types/jest": "^29.2.4",
"@types/node": "^16.18.3",
"@types/pg": "^8.6.5",
"@types/pg-format": "^1.0.1",
"@types/prettier": "^2.7.3",
"cpy-cli": "^4.1.0",
"jest": "^29.3.1",
"nodemon": "^2.0.20",
Expand Down
22 changes: 16 additions & 6 deletions src/server/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,27 @@ export const CRYPTO_KEY = (await getSecret('CRYPTO_KEY')) || 'SAMPLE_KEY'
const PG_META_DB_HOST = process.env.PG_META_DB_HOST || 'localhost'
const PG_META_DB_NAME = process.env.PG_META_DB_NAME || 'postgres'
const PG_META_DB_USER = process.env.PG_META_DB_USER || 'postgres'
const PG_META_DB_PORT = Number(process.env.PG_META_DB_PORT) || 5432
const PG_META_DB_PORT = process.env.PG_META_DB_PORT || '5432'
const PG_META_DB_PASSWORD = (await getSecret('PG_META_DB_PASSWORD')) || 'postgres'
const PG_META_DB_SSL_MODE = process.env.PG_META_DB_SSL_MODE || 'disable'
const PG_META_DB_SSL_ROOT_CERT_PATH = process.env.PG_META_DB_SSL_ROOT_CERT_PATH

const PG_CONN_TIMEOUT_SECS = Number(process.env.PG_CONN_TIMEOUT_SECS || 15)

export const PG_CONNECTION =
process.env.PG_META_DB_URL ||
`postgres://${PG_META_DB_USER}:${encodeURIComponent(
PG_META_DB_PASSWORD
)}@${PG_META_DB_HOST}:${PG_META_DB_PORT}/${PG_META_DB_NAME}?sslmode=${PG_META_DB_SSL_MODE}`
export let PG_CONNECTION = process.env.PG_META_DB_URL
if (!PG_CONNECTION) {
const pgConn = new URL('postgresql://')
pgConn.hostname = PG_META_DB_HOST
pgConn.port = PG_META_DB_PORT
pgConn.username = PG_META_DB_USER
pgConn.password = PG_META_DB_PASSWORD
pgConn.pathname = encodeURIComponent(PG_META_DB_NAME)
pgConn.searchParams.set('sslmode', PG_META_DB_SSL_MODE)
if (PG_META_DB_SSL_ROOT_CERT_PATH) {
pgConn.searchParams.set('sslrootcert', PG_META_DB_SSL_ROOT_CERT_PATH)
}
PG_CONNECTION = `${pgConn}`
}

export const EXPORT_DOCS = process.argv[2] === 'docs' && process.argv[3] === 'export'
export const GENERATE_TYPES =
Expand Down
3 changes: 3 additions & 0 deletions test/db/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM supabase/postgres:14.1.0

COPY --chown=postgres:postgres --chmod=600 server.key server.crt /var/lib/postgresql/
8 changes: 4 additions & 4 deletions test/db/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
services:
db:
image: supabase/postgres:14.1.0
build: .
ports:
- 5432:5432
volumes:
- .:/docker-entrypoint-initdb.d
environment:
- .:/docker-entrypoint-initdb.d
environment:
POSTGRES_PASSWORD: postgres
command: postgres -c config_file=/etc/postgresql/postgresql.conf
command: postgres -c config_file=/etc/postgresql/postgresql.conf -c ssl=on -c ssl_cert_file=/var/lib/postgresql/server.crt -c ssl_key_file=/var/lib/postgresql/server.key
77 changes: 77 additions & 0 deletions test/db/server.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
41:a3:0e:d5:2f:07:82:95:c1:cc:c8:62:02:04:eb:7b:25:dc:3e:6b
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = localhost
Validity
Not Before: Aug 2 10:31:43 2023 GMT
Not After : Jul 30 10:31:43 2033 GMT
Subject: CN = localhost
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:d6:4a:ec:0d:40:a8:b1:cd:e8:e9:16:41:a9:6b:
ed:7f:c4:ee:4e:b6:4e:83:5a:7c:37:81:8c:fd:90:
07:da:57:d3:1b:91:2f:77:6d:a1:b0:38:48:08:03:
1f:77:91:6a:91:39:54:06:87:20:33:c2:d9:20:e4:
06:15:f9:59:fb:0e:db:2e:a0:81:c0:6c:47:f6:bc:
00:0f:07:9a:36:a8:4c:c3:62:97:51:31:53:53:51:
2a:d6:ff:ca:e6:cf:b2:8e:d7:89:ae:2b:a4:15:ed:
7c:35:8e:5b:26:84:b1:4d:13:7a:3e:32:a3:56:53:
c1:e8:98:f2:4a:03:56:53:2e:db:c7:96:7e:d2:df:
ea:e5:d7:c2:35:93:61:0d:af:0c:c0:2e:b4:b2:a2:
b1:5a:8b:38:fa:e6:1c:c7:1e:20:d8:0e:b2:97:f2:
82:6b:4a:1f:27:8c:c1:e4:63:df:42:9a:e3:6c:46:
74:46:fb:f5:0e:12:d4:b9:12:ce:dc:22:dd:f0:5c:
6e:e3:31:4f:1a:fa:de:31:15:ec:2a:9b:6c:ea:67:
bf:67:f7:13:44:ba:01:4a:dd:76:32:a8:59:82:13:
81:f2:48:6d:f4:5d:f0:70:a1:7b:f0:be:46:3e:65:
36:ee:f3:2e:39:00:52:2a:00:f3:d3:83:c9:55:56:
dd:93
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
79:57:F3:18:B8:6B:FB:64:39:B0:E8:CC:24:18:ED:C0:C1:37:E2:0D
X509v3 Authority Key Identifier:
79:57:F3:18:B8:6B:FB:64:39:B0:E8:CC:24:18:ED:C0:C1:37:E2:0D
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
2b:d1:37:75:b5:92:9a:c9:ed:45:a6:46:ac:97:93:b9:bf:c0:
f3:7f:47:c3:bd:fd:bd:6b:58:ad:49:79:9d:31:18:3c:b9:94:
4b:aa:ca:49:c9:04:c4:71:1f:62:9b:ce:3f:5a:24:ec:82:68:
a7:74:45:dd:b1:02:8a:f0:f2:4f:7f:3d:28:94:b0:5b:47:51:
f3:12:a5:ce:1b:32:9f:f8:c6:6a:61:c6:99:4c:f6:99:9e:44:
e4:e9:01:0c:45:1c:a4:5f:f3:69:2e:3d:a7:5d:62:ab:fb:e4:
ea:d2:56:0f:56:df:00:5d:fa:9e:62:2a:77:00:cd:cd:b4:d8:
b6:47:4b:84:73:85:3e:eb:4c:3e:2b:67:46:84:b1:22:1a:04:
47:02:ca:a0:74:a5:97:28:89:56:aa:c6:4a:ce:97:9b:14:14:
96:d7:26:60:38:fd:ec:ae:7d:ea:47:68:16:1c:ee:47:19:10:
69:6a:25:67:71:ac:0b:f0:4a:b0:b3:e6:9b:5f:89:e8:e7:64:
f7:92:37:0c:72:8c:d0:32:c5:10:79:c1:2e:22:05:65:50:db:
d8:0e:bf:b6:d9:f1:7b:88:82:0e:be:06:9b:8c:96:e2:53:03:
1f:de:86:39:d8:7e:4b:48:bb:11:d9:5d:41:68:82:49:e4:2b:
33:79:1b:78
-----BEGIN CERTIFICATE-----
MIIDCTCCAfGgAwIBAgIUQaMO1S8HgpXBzMhiAgTreyXcPmswDQYJKoZIhvcNAQEL
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIzMDgwMjEwMzE0M1oXDTMzMDcz
MDEwMzE0M1owFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEA1krsDUCosc3o6RZBqWvtf8TuTrZOg1p8N4GM/ZAH2lfT
G5Evd22hsDhICAMfd5FqkTlUBocgM8LZIOQGFflZ+w7bLqCBwGxH9rwADweaNqhM
w2KXUTFTU1Eq1v/K5s+yjteJriukFe18NY5bJoSxTRN6PjKjVlPB6JjySgNWUy7b
x5Z+0t/q5dfCNZNhDa8MwC60sqKxWos4+uYcxx4g2A6yl/KCa0ofJ4zB5GPfQprj
bEZ0Rvv1DhLUuRLO3CLd8Fxu4zFPGvreMRXsKpts6me/Z/cTRLoBSt12MqhZghOB
8kht9F3wcKF78L5GPmU27vMuOQBSKgDz04PJVVbdkwIDAQABo1MwUTAdBgNVHQ4E
FgQUeVfzGLhr+2Q5sOjMJBjtwME34g0wHwYDVR0jBBgwFoAUeVfzGLhr+2Q5sOjM
JBjtwME34g0wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAK9E3
dbWSmsntRaZGrJeTub/A839Hw739vWtYrUl5nTEYPLmUS6rKSckExHEfYpvOP1ok
7IJop3RF3bECivDyT389KJSwW0dR8xKlzhsyn/jGamHGmUz2mZ5E5OkBDEUcpF/z
aS49p11iq/vk6tJWD1bfAF36nmIqdwDNzbTYtkdLhHOFPutMPitnRoSxIhoERwLK
oHSllyiJVqrGSs6XmxQUltcmYDj97K596kdoFhzuRxkQaWolZ3GsC/BKsLPmm1+J
6Odk95I3DHKM0DLFEHnBLiIFZVDb2A6/ttnxe4iCDr4Gm4yW4lMDH96GOdh+S0i7
EdldQWiCSeQrM3kbeA==
-----END CERTIFICATE-----
28 changes: 28 additions & 0 deletions test/db/server.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDWSuwNQKixzejp
FkGpa+1/xO5Otk6DWnw3gYz9kAfaV9MbkS93baGwOEgIAx93kWqROVQGhyAzwtkg
5AYV+Vn7DtsuoIHAbEf2vAAPB5o2qEzDYpdRMVNTUSrW/8rmz7KO14muK6QV7Xw1
jlsmhLFNE3o+MqNWU8HomPJKA1ZTLtvHln7S3+rl18I1k2ENrwzALrSyorFaizj6
5hzHHiDYDrKX8oJrSh8njMHkY99CmuNsRnRG+/UOEtS5Es7cIt3wXG7jMU8a+t4x
Fewqm2zqZ79n9xNEugFK3XYyqFmCE4HySG30XfBwoXvwvkY+ZTbu8y45AFIqAPPT
g8lVVt2TAgMBAAECggEAHXE9I3OpzzF3pGbEGMSqZJlTFgoi7sCE5pTBy/4jsL0g
/92fxEHngDBgvTETUWNFCApKCtI6phdJq8+IgoZi9YU3Wh2qwMcKetJJE8eQnvKF
XCb0nAQx6vWbnt9AKnGI7+qZ5mM6moSplyt68eeIpgqyC0+mdMWck8TygnbDlTlP
W+lfAZoCnrPDe6ptKTKtSy3AdGteAKk0pdaiUPHjtMdtOMwXCcHQkKopVIstfAib
mvg2/3djn5OnYBmhOINIAZvNSoVr/s9I/yZc8V3z2/lPoLDRmEjCgIGba4zkG0Sr
oaHdxJz8eTuSPwI+jcjto3gPkBdL2658l4JLxXYgQQKBgQD+VWv+jJsB01ijZsI9
cV1aS6bqyb5sJEc1EFOZtkUYEr0RB6ww4FrRY7uryMPjXf+y47RvGsev0GvWkpRZ
ijzGmfeqHMm9y+hjVxJ64nNOvxzpuVWG0s3JOBDnVY/4RmnW1qghlAI0QkwU7EHl
O4ql3QS5PQEzudhNpQltDHmL4QKBgQDXsleHOzf32HCFR3EWAy+rosuiianGu3LI
2toAX0NxCSkNCPHksfcEryoyrgKLCSzNoBtQMQkvk9sgbQfRLPZi3Lcng+wzjBEv
4uR/a2xdOwnCMCYc9KMjnVukhf5WZ+hJBc49lCqJtc4Mhl89icgrXxUG8YwqUqNK
qb9YMCH38wKBgE3JOnpj7pSkWxu+tfGs1mxjbu2oPkE85zpnf+onQQKX2JN40UUx
mRUpd6CWirLjcOz5j5nbiu9Ow2yg8BZinSvwszqoC1utHaokW1aSI8oV0XX6ZRoT
JzU/nIvkM2AvyPcYN9vtNK9fB33utEiz6TfJXUR6T//N+0XkD/n2MsaBAoGBALDY
A3NYVhbaWcasQEdv7VGnc5WbkJrjbMTIyhur/ztZ61JIlyqNzp0EkHBkwqkDqLwe
HMaurX1YmDwJqHMTjh6YH4JCYxIQMLc2K2lcxcfac7HGkDkFSgwVI+HMCi8Fmijk
nadXJ1koufsC4Gsv3/HPTwoWWHkKr96zNbI0JGWJAoGAFFw+fjx4gI+VDayf4NMd
feIpDF6O2uB9uKbTyNJjYoj9Jh0NkSHccgVb+j5BvnxBmAJHrMEr6Cz3bnlKlK0a
1+Oqyq8MaYRLk6J/xMGSUcfa3uRC5svq0s8ebbl84Kt23IW9NU+YycVnMzysMLsH
xn4VooZdfd3oNm2lpYURz3I=
-----END PRIVATE KEY-----
1 change: 1 addition & 0 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ import './server/column-privileges'
import './server/materialized-views'
import './server/table-privileges'
import './server/typegen'
import './server/ssl'
66 changes: 66 additions & 0 deletions test/server/ssl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import CryptoJS from 'crypto-js'
import path from 'path'
import { fileURLToPath } from 'url'
import { app } from './utils'
import { CRYPTO_KEY } from '../../src/server/constants'

// @ts-ignore: Harmless type error on import.meta.
const cwd = path.dirname(fileURLToPath(import.meta.url))
const SSL_ROOT_CERT_PATH = path.join(cwd, '../db/server.crt')

test('query with no ssl', async () => {
const res = await app.inject({
method: 'POST',
path: '/query',
headers: {
'x-connection-encrypted': CryptoJS.AES.encrypt(
'postgresql://postgres:postgres@localhost:5432/postgres',
CRYPTO_KEY
).toString(),
},
payload: { query: 'select 1;' },
})
expect(res.json()).toMatchInlineSnapshot(`
[
{
"?column?": 1,
},
]
`)
})

test('query with ssl w/o root cert', async () => {
const res = await app.inject({
method: 'POST',
path: '/query',
headers: {
'x-connection-encrypted': CryptoJS.AES.encrypt(
'postgresql://postgres:postgres@localhost:5432/postgres?sslmode=verify-full',
CRYPTO_KEY
).toString(),
},
payload: { query: 'select 1;' },
})
expect(res.json()?.error).toMatch(/^self[ -]signed certificate$/)
})

test('query with ssl with root cert', async () => {
const res = await app.inject({
method: 'POST',
path: '/query',
headers: {
'x-connection-encrypted': CryptoJS.AES.encrypt(
`postgresql://postgres:postgres@localhost:5432/postgres?sslmode=verify-full&sslrootcert=${SSL_ROOT_CERT_PATH}`,
CRYPTO_KEY
).toString(),
},
payload: { query: 'select 1;' },
})
expect(res.json()).toMatchInlineSnapshot(`
[
{
"?column?": 1,
},
]
`)
})

0 comments on commit 3514106

Please sign in to comment.