diff --git a/.travis.yml b/.travis.yml index 8adb26836..011bd9e01 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,6 +43,38 @@ matrix: postgresql: '9.5' dist: precise + # Run tests/paths with client certificate authentication + - node_js: lts/* + env: + - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres + PGSSLMODE=verify-full + PGSSLROOTCERT=$TRAVIS_BUILD_DIR/packages/pg/test/tls/test-server-ca.crt + PGSSLCERT=$TRAVIS_BUILD_DIR/packages/pg/test/tls/test-client.crt + PGSSLKEY=$TRAVIS_BUILD_DIR/packages/pg/test/tls/test-client.key + PG_CLIENT_CERT_TEST=1 + before_script: + - chmod go= packages/pg/test/tls/test-client.key + - | + sudo sed -i \ + -e '/^ssl_cert_file =/d' \ + -e '/^ssl_key_file =/d' \ + /etc/postgresql/10/main/postgresql.conf + + cat <<'travis ci breaks heredoc' | sudo tee -a /etc/postgresql/10/main/postgresql.conf > /dev/null + ssl_cert_file = 'test-server.crt' + ssl_key_file = 'test-server.key' + ssl_ca_file = 'test-client-ca.crt' + + - printf 'hostssl all all %s cert\n' 127.0.0.1/32 ::1/128 | sudo tee /etc/postgresql/10/main/pg_hba.conf > /dev/null + - sudo make -C packages/pg/test/tls install DESTDIR=/var/ramfs/postgresql/10/main + - sudo systemctl restart postgresql@10-main + - yarn build + script: + - cd packages/pg + - node test/integration/connection-pool/tls-tests.js + - npm install --no-save pg-native + - node test/integration/connection-pool/tls-tests.js native + # different PostgreSQL versions on Node LTS - node_js: lts/erbium addons: diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index 6bc0952e0..ccb6742c5 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -76,12 +76,18 @@ class Connection extends EventEmitter { return self.emit('error', new Error('There was an error establishing an SSL connection')) } var tls = require('tls') - const options = Object.assign( - { - socket: self.stream, - }, - self.ssl - ) + const options = { + socket: self.stream, + } + + if (self.ssl !== true) { + Object.assign(options, self.ssl) + + if ('key' in self.ssl) { + options.key = self.ssl.key + } + } + if (net.isIP(host) === 0) { options.servername = host } diff --git a/packages/pg/test/integration/connection-pool/tls-tests.js b/packages/pg/test/integration/connection-pool/tls-tests.js new file mode 100644 index 000000000..f85941d45 --- /dev/null +++ b/packages/pg/test/integration/connection-pool/tls-tests.js @@ -0,0 +1,23 @@ +'use strict' + +const fs = require('fs') + +const helper = require('./test-helper') +const pg = helper.pg + +const suite = new helper.Suite() + +if (process.env.PG_CLIENT_CERT_TEST) { + suite.testAsync('client certificate', async () => { + const pool = new pg.Pool({ + ssl: { + ca: fs.readFileSync(process.env.PGSSLROOTCERT), + cert: fs.readFileSync(process.env.PGSSLCERT), + key: fs.readFileSync(process.env.PGSSLKEY), + }, + }) + + await pool.query('SELECT 1') + await pool.end() + }) +} diff --git a/packages/pg/test/tls/GNUmakefile b/packages/pg/test/tls/GNUmakefile new file mode 100644 index 000000000..12d8f49fd --- /dev/null +++ b/packages/pg/test/tls/GNUmakefile @@ -0,0 +1,71 @@ +DESTDIR ::= /var/lib/postgres/data +POSTGRES_USER ::= postgres +POSTGRES_GROUP ::= postgres +DATABASE_HOST ::= localhost +DATABASE_USER ::= postgres + +all: \ + test-server-ca.crt \ + test-client-ca.crt \ + test-server.key \ + test-server.crt \ + test-client.key \ + test-client.crt + +clean: + rm -f \ + test-server-ca.key \ + test-client-ca.key \ + test-server-ca.crt \ + test-client-ca.crt \ + test-server.key \ + test-server.crt \ + test-client.key \ + test-client.crt + +install: test-server.crt test-server.key test-client-ca.crt + install \ + --owner=$(POSTGRES_USER) \ + --group=$(POSTGRES_GROUP) \ + --mode=0600 \ + -t $(DESTDIR) \ + $^ + +test-%-ca.crt: test-%-ca.key + openssl req -new -x509 \ + -subj '/CN=node-postgres test $* CA' \ + -days 3650 \ + -key $< \ + -out $@ + +test-server.csr: test-server.key + openssl req -new \ + -subj '/CN=$(DATABASE_HOST)' \ + -key $< \ + -out $@ + +test-client.csr: test-client.key + openssl req -new \ + -subj '/CN=$(DATABASE_USER)' \ + -key $< \ + -out $@ + +test-%.crt: test-%.csr test-%-ca.crt test-%-ca.key + openssl x509 -req \ + -CA test-$*-ca.crt \ + -CAkey test-$*-ca.key \ + -set_serial 1 \ + -days 3650 \ + -in $< \ + -out $@ + +%.key: + openssl genpkey \ + -algorithm EC \ + -pkeyopt ec_paramgen_curve:prime256v1 \ + -out $@ + +.PHONY: all clean install +.SECONDARY: test-server-ca.key test-client-ca.key +.INTERMEDIATE: test-server.csr test-client.csr +.POSIX: diff --git a/packages/pg/test/tls/test-client-ca.crt b/packages/pg/test/tls/test-client-ca.crt new file mode 100644 index 000000000..c2c5c040a --- /dev/null +++ b/packages/pg/test/tls/test-client-ca.crt @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBozCCAUmgAwIBAgIUNYMF06PrmjsMR6x+C8k5YZn9heAwCgYIKoZIzj0EAwIw +JzElMCMGA1UEAwwcbm9kZS1wb3N0Z3JlcyB0ZXN0IGNsaWVudCBDQTAeFw0yMDEw +MzExOTI1NDdaFw0zMDEwMjkxOTI1NDdaMCcxJTAjBgNVBAMMHG5vZGUtcG9zdGdy +ZXMgdGVzdCBjbGllbnQgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASI/Efx +Pq0P54VKPkTUOTwBH1iuYbnLpd4kAGjb1E334/p9CEBbDREVSqDjYjWswFybxKIF +ooKXtMpEMJfymJAUo1MwUTAdBgNVHQ4EFgQU/b/FRwYZ5/VMjdesIolksiqNYK4w +HwYDVR0jBBgwFoAU/b/FRwYZ5/VMjdesIolksiqNYK4wDwYDVR0TAQH/BAUwAwEB +/zAKBggqhkjOPQQDAgNIADBFAiEApHFCAWGbRGqYkyiBO+gMyX6gF5oFJywUupZP +LfgIRDACIDBZotzPe6+BIl2fU9Xgm7CxV6cCoX8bPEJKveKMnOaN +-----END CERTIFICATE----- diff --git a/packages/pg/test/tls/test-client-ca.key b/packages/pg/test/tls/test-client-ca.key new file mode 100644 index 000000000..86a4cb4a0 --- /dev/null +++ b/packages/pg/test/tls/test-client-ca.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgKsipfQWM+41FriF7 +kRxVaiNi8qY1fzLx6Dp/gUQQPG6hRANCAASI/EfxPq0P54VKPkTUOTwBH1iuYbnL +pd4kAGjb1E334/p9CEBbDREVSqDjYjWswFybxKIFooKXtMpEMJfymJAU +-----END PRIVATE KEY----- diff --git a/packages/pg/test/tls/test-client.crt b/packages/pg/test/tls/test-client.crt new file mode 100644 index 000000000..2d2a8996d --- /dev/null +++ b/packages/pg/test/tls/test-client.crt @@ -0,0 +1,9 @@ +-----BEGIN CERTIFICATE----- +MIIBITCByAIBATAKBggqhkjOPQQDAjAnMSUwIwYDVQQDDBxub2RlLXBvc3RncmVz +IHRlc3QgY2xpZW50IENBMB4XDTIwMTAzMTE5MjU0N1oXDTMwMTAyOTE5MjU0N1ow +EzERMA8GA1UEAwwIcG9zdGdyZXMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARY +4j5AgTLi/O/UTB8l1mX+nD9u3SW9RwN1mekcqEZqCpOPMsQEQ/HLxaKnoSTD6w/G +NqrBnHlbMGPwEdKvV96bMAoGCCqGSM49BAMCA0gAMEUCIQDzfjm+BzmjrsIO4QRu +Et0ShHBK3Kley3oqnzoJHCUSmAIgdF5gELQ5mlJVX3bAI8h1cKiC/L6awwg7eBDU +S1gBTaI= +-----END CERTIFICATE----- diff --git a/packages/pg/test/tls/test-client.key b/packages/pg/test/tls/test-client.key new file mode 100644 index 000000000..662f35532 --- /dev/null +++ b/packages/pg/test/tls/test-client.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgL9jW07+fXy/74Ub3 +579RXm0Xpo7lnNnQleSzkTEXCrmhRANCAARY4j5AgTLi/O/UTB8l1mX+nD9u3SW9 +RwN1mekcqEZqCpOPMsQEQ/HLxaKnoSTD6w/GNqrBnHlbMGPwEdKvV96b +-----END PRIVATE KEY----- diff --git a/packages/pg/test/tls/test-server-ca.crt b/packages/pg/test/tls/test-server-ca.crt new file mode 100644 index 000000000..ac3427561 --- /dev/null +++ b/packages/pg/test/tls/test-server-ca.crt @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBozCCAUmgAwIBAgIUD582G2ou0Lg9q7AJeAMpiQVaiPQwCgYIKoZIzj0EAwIw +JzElMCMGA1UEAwwcbm9kZS1wb3N0Z3JlcyB0ZXN0IHNlcnZlciBDQTAeFw0yMDEw +MzExOTI1NDdaFw0zMDEwMjkxOTI1NDdaMCcxJTAjBgNVBAMMHG5vZGUtcG9zdGdy +ZXMgdGVzdCBzZXJ2ZXIgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT/jGRh +FiZu96o0hfgIkep4PusTwI6P1ASFh8LgnUu2bMcIlYakQK0ap2XvCaSl9675+Lu9 +yNZaSZVA5LpFICXto1MwUTAdBgNVHQ4EFgQUHI1BK+6u7r9r1XhighuP2/eGcQUw +HwYDVR0jBBgwFoAUHI1BK+6u7r9r1XhighuP2/eGcQUwDwYDVR0TAQH/BAUwAwEB +/zAKBggqhkjOPQQDAgNIADBFAiALwBWN9pRpaGQ12G9ERACn8/6RtAoO4lI5RmaR +rsTHtAIhAJxMfzNIgBAgX7vBSjHaqA08CozIctDSVag/rDlAzgy0 +-----END CERTIFICATE----- diff --git a/packages/pg/test/tls/test-server-ca.key b/packages/pg/test/tls/test-server-ca.key new file mode 100644 index 000000000..bfc4925ec --- /dev/null +++ b/packages/pg/test/tls/test-server-ca.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgyUd4vHDNrEFzfttP +z+AFp3Tbyui+b3i9YDW7VqpMOIKhRANCAAT/jGRhFiZu96o0hfgIkep4PusTwI6P +1ASFh8LgnUu2bMcIlYakQK0ap2XvCaSl9675+Lu9yNZaSZVA5LpFICXt +-----END PRIVATE KEY----- diff --git a/packages/pg/test/tls/test-server.crt b/packages/pg/test/tls/test-server.crt new file mode 100644 index 000000000..171700d5d --- /dev/null +++ b/packages/pg/test/tls/test-server.crt @@ -0,0 +1,9 @@ +-----BEGIN CERTIFICATE----- +MIIBITCByQIBATAKBggqhkjOPQQDAjAnMSUwIwYDVQQDDBxub2RlLXBvc3RncmVz +IHRlc3Qgc2VydmVyIENBMB4XDTIwMTAzMTE5MjU0N1oXDTMwMTAyOTE5MjU0N1ow +FDESMBAGA1UEAwwJbG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +4Mwi6dHeWRZ2QU19a5ykq6gJfIVJDEaJqNlWXk/5/laiGy8ScBV0YAlvk9xsfAyU +YDxcQTjQkeC0bbzhdEPjNjAKBggqhkjOPQQDAgNHADBEAiB+DW/8Kg3tuoovAE+8 +1Pv/8OkF3MD4A1ztULkW3KJ4PwIgMn7ea3HrEQJoeSKFe1kKIgNrHftdC5kZQYj5 +uNXYpLo= +-----END CERTIFICATE----- diff --git a/packages/pg/test/tls/test-server.key b/packages/pg/test/tls/test-server.key new file mode 100644 index 000000000..1ce884e2f --- /dev/null +++ b/packages/pg/test/tls/test-server.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgBoW9xxWBH2tHiPFk +9ajPALHyw0lHAY1DF8WvHQNodx2hRANCAATgzCLp0d5ZFnZBTX1rnKSrqAl8hUkM +Romo2VZeT/n+VqIbLxJwFXRgCW+T3Gx8DJRgPFxBONCR4LRtvOF0Q+M2 +-----END PRIVATE KEY-----