简体   繁体   中英

SSL for PostgreSQL connection nodejs

I am trying to connect to my Heroku PostgreSQL DB and I keep getting an SSL error. Does anyone have an idea on how to enable SSL in the connection string?

postgres://user:pass@host:port/database;

Been looking for it everywhere but it does not seem to be a very popular topic. By the way, I am running Nodejs and the node-pg module with its connection-pooled method:

pg.connect(connString, function(err, client, done) {
  // Should work.
});

Comments are much appreciated.

你可以这样实现:

postgres://user:pass@host:port/database?ssl=true

You also can use this code below when create a new Client from node-postgres :

var pg = require("pg");

var client = new pg.Client({
  user: "yourUser",
  password: "yourPass",
  database: "yourDatabase",
  port: 5432,
  host: "host.com",
  ssl: true
});

client.connect();

var query = client.query('CREATE TABLE people(id SERIAL PRIMARY KEY, name VARCHAR(100) not null)');

query.on('row', function(row) {
  console.log(row.name);
});

query.on('end', client.end.bind(client));

Hope this helps!

With Google Cloud PG and pg-promise I had a similar need. The error I got (using ?ssl=true ) was connection requires a valid client certificate .

SSL connection is not documented for pg-promise but it is built on node-postgres . As explained in the link, the ssl config parameter can be more than just true :

const pgp = require('pg-promise')();
const fs = require('fs');

const connectionConf = {
    host: 'myhost.com',
    port: 5432,
    database: 'specific_db_name',
    user: 'my_App_user',
    password: 'aSecretePass',
    ssl: {
        rejectUnauthorized : false,
        ca   : fs.readFileSync("server-ca.pem").toString(),
        key  : fs.readFileSync("client-key.pem").toString(),
        cert : fs.readFileSync("client-cert.pem").toString(),
  }

};
const new_db = pgp(connectionConf);
new_db.any('SELECT * FROM interesting_table_a LIMIT 10')
    .then(res => {console.log(res);})
    .catch(err => {console.error(err);})
    .then(() => {new_db.$pool.end()});

For anybody looking for a TypeORM solution, it's also {ssl: true} .

Full example:

 const connectionOptions: PostgresConnectionOptions = { name: `default`, type: `postgres`, url: process.env.DATABASE_URL, ssl: process.env.DATABASE_SSL === `true` }

I have the same problem. As for today, there is a problem with pg >= 8.0.0 . So if you have this problem use pg version 7 and below.

yarn add pg@7

You can also use environment variables to set up the connection. Here is an example.

(Assuming you have a Postgres DB running on port 5432@localhost and the DB supports SSL connection)

.env

PGHOST=localhost
PGPORT=5432
PGDATABASE=mydb
PGUSER=pguser1
PGPASSWORD=mypassword
PGSSLMODE=require

(Ensure you set PGSSLMODE to require as shown above.)

db.js

require('dotenv').config()
const { Pool } = require('pg')

// pools will use environment variables for connection information
const pool = new Pool()
// const pool = new Pool({ ssl: true }); This works too in the absence of PGSSLMODE
pool.on('error', function (err) {
    console.log('idle client error', err.message, err.stack)
})

module.exports = {
    pool,
    query: (text, params, callback) => {
        return pool.query(text, params, callback)
    }
}

server.js

const express = require('express')
const { pool } = require('./db')

const app = express()
const port = 3000

app.get('/', async (req, res) => {
  console.log('Request received...')
  const result = await pool.query(`SELECT * FROM organization`);
  res.send(result)
})

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

Note : in case your Postgres database does not support SSL connections, you will have the following error when your application tries to make a query:

Error: The server does not support SSL connections
at Socket.<anonymous> (node_modules/pg/lib/connection.js:87:35)

References:

If none of the above work.

Consider my case, was working before and recently switched work stations - suddenly not working anymore and giving the abovementioned error.

The reason was that I cloned a GitHub repo (my own) that had calls to private variables after switching computers. The repo did not have a .env file (obviously) which contained the database connection string along with many other variables. Thus, my call to it in the code no longer worked until I created the .env file locally.

TLDR

// database_config.js
const { Client } = require("pg");
const client = new Client({
  connectionString: process.env.DATABASE_CONNECTION, // <--- not defined without .env file definition
  ssl: {
    rejectUnauthorized: false,
  },
});

client
.connect()
.then(() => console.log("connected to database"))
.catch((err) => console.error(err));

module.exports = client;

SOLUTION

// .env
DATABASE_CONNECTION = your_connection_string
const sequelize = new Sequelize(
    configuration.get("postgresConnectionString"),
    {
        logging: false,
        dialectOptions: {
            ssl: {
                ca: fs.readFileSync(path.join(__dirname, "/ssl/DigiCertGlobalRootG2.crt.pem")),
                rejectUnauthorized: true,
                require: true,
            },
        },
    },
);

DigiCertGlobalRootG2.crt.pem: Is a combination of 2 key for constitency(BaltimoreCyberTrustRoot.crt.pem gonna expiry soon).One file with multiple keys as ----- BEGIN CERTIFICATE ----- BaltimoreCyberTrustRoot.crt.pem ----- END CERTIFICATE ----- ----- BEGIN CERTIFICATE ----- DigiCertGlobalRootG2.crt.pem -----END CERTIFICATE----- Connecting to Azure postgress from node.js application using Sequelize ORM with support of SSL.
DigiCertGlobalRootG2.crt.pem: You will get it from the Azure portal .

Note: If not using any key then ssl configuration is like this:

const sequelize = new Sequelize(
    configuration.get("postgresConnectionString"),
    {
        logging: false,
        dialectOptions: {
            ssl: true,
        },
    },
);

Note: Please check the connectionString ends with sslmode=require|| ssl_ca=required: https://docs.microsoft.com/en-us/azure/mysql/concepts-certificate-rotationsslmode=require|| ssl_ca=required: https://docs.microsoft.com/en-us/azure/mysql/concepts-certificate-rotation , based this, please add SSL configuration accordingly Note: The content you feel need a change , please let me know

If you are using AWS RDS Proxy for Postgresql then ssl: true is sufficient. complete example is here

let getConnection = async () => {
    let connParam = {
        host: {RDS_PROXY_URL},
        port: {PORT},
        user: {USERNAME},
        database : {DB_ANME},
        password: {PASSWORD},
        ssl: true
    };
    
    let pgClient = new pg.Client(connParam);

    await pgClient.connect();

    return pgClient;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM