Question

Can't connect to Managed Database ('SELF_SIGNED_CERT_IN_CHAIN' error)

Hi!

I just created a new Managed Database with PostgreSQL at DigitalOcean.

Now, i’m trying to connect with node.js and i’m getting the following error:

(node:15100) UnhandledPromiseRejectionWarning: Error: self signed certificate in certificate chain
    at TLSSocket.onConnectSecure (_tls_wrap.js:1321:34)
    at TLSSocket.emit (events.js:210:5)
    at TLSSocket._finishInit (_tls_wrap.js:794:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:608:12)
(node:15100) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:15100) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Error: Connection terminated unexpectedly
    at Connection.<anonymous> (C:\Users\luizh\Documents\abacate\node_modules\pg\lib\client.js:252:9)
    at Object.onceWrapper (events.js:299:28)
    at Connection.emit (events.js:210:5)
    at Socket.<anonymous> (C:\Users\luizh\Documents\abacate\node_modules\pg\lib\connection.js:76:10)
    at Socket.emit (events.js:215:7)
    at TCP.<anonymous> (net.js:659:12) undefined
Error: self signed certificate in certificate chain
    at TLSSocket.onConnectSecure (_tls_wrap.js:1321:34)
    at TLSSocket.emit (events.js:210:5)
    at TLSSocket._finishInit (_tls_wrap.js:794:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:608:12) {
  code: 'SELF_SIGNED_CERT_IN_CHAIN'
} undefined

This is my code:

const connectionString = 'postgresql://doadmin:xxxx@db-cookify-do-user-6685692-0.db.ondigitalocean.com:25060/defaultdb?sslmode=require&ssl=true'
const pool = new Pool({
  connectionString: connectionString,
  ssl: true,
})

If i run my script with NODE_TLS_REJECT_UNAUTHORIZED=0, it works well.

Anybody can help me with this?

Show comments

Submit an answer

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Sign In or Sign Up to Answer

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Want to learn more? Join the DigitalOcean Community!

Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in Q&A, subscribe to topics of interest, and get courses and tools that will help you grow as a developer and scale your project or business.

You need to pass { rejectUnauthorized: false } as the ssl option.

I used the following script, but with sensitive values removed:

const { Sequelize } = require('sequelize');

const sequelize = new Sequelize({
  dialect: 'postgres',
  host: '',
  port: 0,
  username: '',
  password: '',
  database: '',
  dialectOptions: {
    ssl: { rejectUnauthorized: false },
  },
});

sequelize.authenticate().then(
  () => console.log('success'),
  (error) => console.error(error),
);

The simplest way to verify this is to run:

kubectl run -ti test-pg-connection --image node:12-slim -- bash

Then inside the container type:

mkdir app
cd app
yarn init
yarn add sequelize pg pg-hstore
node

Modify the script and paste it into the node console.

Seems to be an issue with the pg package. Rolling back to version 7.12.1 solves the issue for me.

I don’t think rejectUnauthorized: false is the right option. You typically want to reject unauthorized identities. Not verifying the identity of the server has the potential to leave you open to a man-in-the-middle attack.

Digital Ocean provides the CA certificate in the database connection details. Download the CA certificate and ensure you are connecting to the database using that certificate.

If you’re using knex, your knexfile would resemble the following:

const fs = require("fs");

module.exports = {

    development: {
        client: "pg",
        connection: {
            database: "<database name>",
            user: "<username>",
            password: "<password>",
            host: "<host>",
            port: "<port>",
            ssl: {
                // Ensure we *are* rejecting unauthorized identities 
                rejectUnauthorized: true, 

                // Path to the downloaded digital ocean cert
                ca: fs.readFileSync("ca-certificate.crt").toString()
            },
        },

        ... other knex settings such as pool
    }

}