Sailsjs Heroku Postgresql Error: self signed certificate - node.js

I am new to sails.js and I deployed to heroku and also added a heroku postgreql addon. In my datastore.js file, I added the following configuration so I could migrate my models to the new database addon.
Here is a snippet of my datastore.js file.
adapter: "sails-postgresql",
// URL: my-postgresql-url
// ssl: true,
In my production.js file here's a snippet of the datastore.
adapter: "sails-postgresql",
url: process.env.DATABASE_URL,
ssl: true,
I don't know what seems to be the issue, but this error keeps getting thrown by the server
{
error: Error: self signed certificate
at TLSSocket.onConnectSecure (_tls_wrap.js:1498:34)
at TLSSocket.emit (events.js:314:20)
at TLSSocket.EventEmitter.emit (domain.js:486:12)
at TLSSocket._finishInit (_tls_wrap.js:933:8)
at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:707:12) {
code: 'DEPTH_ZERO_SELF_SIGNED_CERT'
},
meta: {
adapter: 'sails-postgresql',
url: 'my-postgresql-url',
ssl: true,
identity: 'default'
}
}
I don't know what exactly to do, any help would be welcome. Thank you.

Okay, after reading different articles and googling, to solve the issue, I just had to do this.
ssl: {
rejectUnauthorized: false
}
and that fixed the issue.

Hit this problem overnight. Some fiddling and identified that there are additional properties needed in the SSL setup:
A working datastore object for Heroku PostgreSQL is as follows:
datastores: {
default: {
adapter: 'sails-postgresql',
url: process.env.DATABASE_URL,
ssl: {
sslmode: 'require',
rejectUnauthorized: false,
}
},
},

Related

How to download a resource using https behind a proxy without using "rejectUnauthorized: false"?

I'm trying to download https://www.stackoverflow.com or https://www.google.com using got while I'm behind a proxy
I keep running into this error RequestError: unable to get local issue if rejectUnauthorized: false is not used. I know that this rejectUnauthorized: false workaround is a security issue.
stackoverflow.com and google.com must have trusted well-known CAs, so why am I getting this error?
import got from "got";
import { HttpsProxyAgent } from "hpagent";
const result = await got("https://www.google.com", {
agent: {
https: new HttpsProxyAgent({
proxy: process.env.https_proxy,
rejectUnauthorized: false, // If true => RequestError: unable to get local issuer certificate
}),
},
}).text();
console.log("result:", result);
On the other hand, this request to https://jsonplaceholder.typicode.com works without setting rejectUnauthorized: false
const result = await got("https://jsonplaceholder.typicode.com", {
agent: {
https: new HttpsProxyAgent({
proxy: process.env.https_proxy,
}),
},
}).text();
Can you please explain this inconsistency and how to resolve it?
Note: I'm using Node.js 14.17.6

How to use mssql connection using ip/instance?

I'm trying to connect to a production SQL Server instance but it fails to connect.
Could anyone help?
I'm grateful for the community's attention.
.env:
MSSQL_SERVER=ip/instance
MSSQL_PORT=1433
MSSQL_USER=sa
MSSQL_PASSWORD=password
MSSQL_DB_NAME=database
Error:
Failed to connect to ip/instance:1433 - getaddrinfo
ENOTFOUND ip/instance
adonisjs#lucid
mssql: {
client: "mssql",
connection: {
user: Env.get("MSSQL_USER"),
port: parseInt(Env.get("MSSQL_PORT")),
server: Env.get("MSSQL_SERVER"),
password: Env.get("MSSQL_PASSWORD", ""),
database: Env.get("MSSQL_DB_NAME")
},
healthCheck: false,
debug: false,
},
Code:
Database.connection('mssql').from('dbo.EMP').select('*')
Thank you. Its work with -
options: { encrypt: false, // for azure trustServerCertificate: true, // change to true for local dev / self-signed certs

Nodejs mssql server connection throws an error

I want to connect my mssql database from nodejs.
I am using sequelize and tedious module for this.
My connection configs like this
const sequelize = new Sequelize(
"mydb",
"username", "password", {
host:config_data.host,
"dialect":"mssql",
"port":1433
dialectOptions: {
instanceName: "MSSQLSERVER"
},
},
);
When I tried to run script, it throws an error.
(node:14584) UnhandledPromiseRejectionWarning: SequelizeConnectionError: Failed to connect to 192.168.10.220:1433 - Could not connect (sequence)
I apply all steps in configuration manager.
Enabled TCP/IP
Started Server SQL browser
Added 1433 port to Firewall
There is also additional error when host is "localhost".(Currently writed IP address)
(node:13552) UnhandledPromiseRejectionWarning: SequelizeConnectionError: Failed to connect to localhost:1433
- 4292:error:1425F102:SSL routines:ssl_choose_client_version:unsupported protocol:c:\ws\deps\openssl\openssl\ssl\statem\statem_lib.c:1947:
I need to help, is there someone have any idea ?
You need to set encrypt to false in your Sequelize inside options.
const sequelize = new Sequelize(
"mydb",
"username", "password", {
host:config_data.host,
"dialect":"mssql",
"port":1433,
"options": {
encrypt: false,
enableArithAbort: false
},
dialectOptions: {
instanceName: "MSSQLSERVER"
},
},
);
The issue is because of TLS protocol mismatch between Source & Destination server. In my case my App server was Ubuntu 20.04 & my SQL Server(Express 2012) was on Windows server. I also tried to downgrade TLS protocols on Ubuntu but nothing worked. So finally I disabled tls encryption in Sequelize.
Make sure options are given as expected by Sequelize
const sequelize = new Sequelize(dbConfig.DB, dbConfig.USER, dbConfig.PASSWORD, {
host: dbConfig.HOST,
port: dbConfig.PORT,
dialect: dbConfig.dialect,
pool: {
max: dbConfig.pool.max,
min: dbConfig.pool.min,
acquire: dbConfig.pool.acquire,
idle: dbConfig.pool.idle,
},
// The below options are important to supress ssl issue on
// AWS EC2 ubuntu when db server is on windows. There is TLS protocol issue
// Which by using these options we disable tls encryption
dialectOptions: {
// Observe the need for this nested `options` field for MSSQL
options: {
encrypt: false,
enableArithAbort: false
}
}
});

Connect NodeJS to MongoDB Droplet

So I've decided to set up my project with two droplets, a MongoDB image droplet and a NodeJS image droplet. I did so to make it easier to scale both droplets in the future, and other applications may be connecting to the DB in the future, both on Ubuntu 18.04.
I'm getting the error of:
Could not connect to the database: { MongooseServerSelectionError: connection timed out
at new MongooseServerSelectionError (/root/eternal-peace-code/node_modules/mongoose/lib/error/serverSelection.js:22:11)
at NativeConnection.Connection.openUri (/root/eternal-peace-code/node_modules/mongoose/lib/connection.js:808:32)
at Mongoose.connect (/root/eternal-peace-code/node_modules/mongoose/lib/index.js:333:15)
at Timeout.setTimeout [as _onTimeout] (/root/eternal-peace-code/app.js:60:22)
at ontimeout (timers.js:482:11)
at tryOnTimeout (timers.js:317:5)
at Timer.listOnTimeout (timers.js:277:5)
message: 'connection timed out',
name: 'MongooseServerSelectionError',
reason:
TopologyDescription {
type: 'Single',
setName: null,
maxSetVersion: null,
maxElectionId: null,
servers: Map { 'mongo_droplet_ip:27017' => [Object] },
stale: false,
compatible: true,
compatibilityError: null,
logicalSessionTimeoutMinutes: null,
heartbeatFrequencyMS: 10000,
localThresholdMS: 15,
commonWireVersion: null },
[Symbol(mongoErrorContextSymbol)]: {} }
I have set up both servers correctly (so I believe), my MongoDB has two users (both are me but different permissions, I have followed several walkthroughs and so it just happened). My /etc/mongod.conf file has been edited accordingly:
net:
port: 27017
bindIp: 127.0.0.1,mongodb_droplet_ip
security:
authorization: "enabled"
The UFW firewall has HTTPS, SSH and my NodeJS_ip:27017 enabled.
My NodeJS droplet is set up with a domain name pointing to the right IP address, letsencrypt is set up for secure connection at the domain name. The issue I have now is that I can not connect to my Mongo droplet from my NodeJS application, and I would also like to make sure that it is all done securely too.
My NodeJS connect code is using Mongoose and a variables environment file, I also have the whole connect in a timeout function as per another suggestion I saw elsewhere:
setTimeout(async () => {
console.log('Connecting to database...');
const options = {
user: process.env.DBUSER,
pass: process.env.USERPASS,
keepAlive: true,
useNewUrlParser: true,
useFindAndModify: false,
useCreateIndex: true,
useUnifiedTopology: true,
sslCA: cert,
connectTimeoutMS: 5000,
}
await mongoose.connect(process.env.LIVEDB, options)
.then(() => {
console.log('We are connected to the database');
})
.catch(err => {
console.log('Could not connect to the database: ', err);
connectWithTimeout();
});
}, 3000);
I have tried a multitude of things through both droplets but I have wasted around 4 days on getting the project to a staging/production stage so it can launch whenever and just be updated as time goes on.
If you need anything else, please do let me know.
All help would be hugely appreciated,
Thanks
I don't know the URI format you are using. But I got the same issue initially when I tried to connect my node application with Mongo instance of AWS.
Using the long URI sting with all the cluster name like this
mongoURI = 'mongodb://username:password#mongo-instance-shard-00-00-a4iv8.mongodb.net:27017,mongo-instance-shard-00-01-a4iv8.mongodb.net:27017,mongo-instance-shard-00-02-a4iv8.mongodb.net:27017/test?ssl=true&replicaSet=mongo-instance-shard-0&authSource=admin&retryWrites=true&w=majority'
Instead of something like this:
mongodb+srv://server.example.com/
This worked for me. It might help you as well.
Also, found this for digital ocean link
and mongo documentation for the connection string

Can't connect to heroku postgresql database from local node app with sequelize

I'm trying to connect to a Heroku postgresql database from a local nodejs app with Sequelize. I followed this two guides an everything is working perfectly fine on the heroky server side, but my node app won't connect to heroku when I run it locally on my Mac.
http://sequelizejs.com/articles/heroku
https://devcenter.heroku.com/articles/connecting-to-heroku-postgres-databases-from-outside-of-heroku
Here is how I start the local app:
DATABASE_URL=$(heroku config:get DATABASE_URL) nodemon
Gets me:
Sequelize: Unable to connect to the database:
But I get the correct URL by doing this:
echo $(heroku config:get DATABASE_URL)
And those commands are working fine:
heroku pg:psql
psql $(heroku config:get DATABASE_URL)
Here is my nodejs code :
var match = process.env.DATABASE_URL.match(/postgres:\/\/([^:]+):([^#]+)#([^:]+):(\d+)\/(.+)/)
sequelize = new Sequelize(match[5], match[1], match[2], {
dialect: 'postgres',
protocol: 'postgres',
port: match[4],
host: match[3],
logging: false
})
sequelize
.authenticate()
.complete(function(err) {
if (!!err) {
log('Sequelize: Unable to connect to the database:', err);
} else {
http.listen(process.env.PORT || config.server.port, function(){
log('Web server listening on port '+process.env.PORT || config.server.port);
});
}
});
I tried to add native: true to the sequelize options, but then I get:
/Users/clement/Projets/XMM/node_modules/sequelize/lib/sequelize.js:188
throw new Error('The dialect ' + this.getDialect() + ' is not supported.
^
Error: The dialect postgres is not supported. (Error: Please install postgres package manually)
at new module.exports.Sequelize (/Users/clement/Projets/XMM/node_modules/sequelize/lib/sequelize.js:188:13)
at Object.<anonymous> (/Users/clement/Projets/XMM/server.js:17:14)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:929:3
Even after doing:
npm install pg
npm install -g pg
brew install postgresql
This is working by the way:
var pg = require('pg');
pg.connect(process.env.DATABASE_URL+'?ssl=true', function(err, client, done) {
if (err) return console.log(err);
client.query('SELECT * FROM pg_catalog.pg_tables', function(err, result) {
done();
if(err) return console.error(err);
console.log(result.rows);
});
});
But i'd rather use Sequelize.
OK, found the answer by browsing sequelize source code :
https://github.com/sequelize/sequelize/blob/master/lib/dialects/postgres/connection-manager.js#L39
To activate SSL for PG connections you don't need native: true or ssl: true but dialectOptions.ssl: true so the following did finally work:
sequelize = new Sequelize(process.env.DATABASE_URL, {
dialect: 'postgres',
protocol: 'postgres',
dialectOptions: {
ssl: true
}
});
To work around the self signed certificate bug on node-postgres version 8 mentioned at SequelizeConnectionError: self signed certificate you can use instead:
sequelize = new Sequelize(process.env.DATABASE_URL, {
dialect: 'postgres',
protocol: 'postgres',
dialectOptions: {
ssl: {
require: true,
rejectUnauthorized: false
}
}
});
You no longer need to parse the DATABASE_URL env variable, there is a Sequelize constructor which accepts the connection URL:
sequelize = new Sequelize(process.env.DATABASE_URL, {
dialect: 'postgres',
protocol: 'postgres',
dialectOptions: {
ssl: true
}
});
One needs to add dialectOptions under ssl
"development": {
"username": process.env.DB_USERNAME,
"password": process.env.DB_PASSWORD,
"database": process.env.DB_NAME,
"host": process.env.DB_HOST,
"dialect": process.env.DB_DIALECT,
"dialectOptions": {
ssl: {
require: true,
rejectUnauthorized: false
}
}
},
Source is as per official sequelize github
You need just these 2 things
Append ?sslmode=require to your POSTGRES DATABASE URI
Make sure you have rejectUnauthorized: false in your dialectOptions
const sequelize = new Sequelize(`${process.env.DATABASE_URI}?sslmode=require`, {
url: process.env.DATABASE_URI,
dialect: 'postgres',
logging: false,
dialectOptions: {
ssl: {
require: true,
rejectUnauthorized: false, // very important
}
}
}
For More Information, here is an Article on Heroku DevCenter about it
https://devcenter.heroku.com/articles/heroku-postgresql#heroku-postgres-ssl
I had the same problem and for these cases you can consider the following documentation example on how to connect the heroku database:
https://sequelize.readthedocs.io/en/1.7.0/articles/heroku/
At the end i did implement a code like :
const sequelize = new Sequelize(
process.env.DATABASE_NAME_DB_CONFIG,
process.env.USER_NAME_DB_CONFIG,
process.env.USER_PASSWORD_DB_CONFIG,
{
host: process.env.HOST_DB_CONFIG,
dialect: process.env.DIALECT_DB_CONFIG,
protocol: process.env.PROTOCOL_DB_CONFIG,
logging: true,
dialectOptions: {
ssl: true
},
pool: {
max: 5,
min: 0,
idle: 10000
}
}
);
where you need to take account the dialectOptions with ssl: true.
That's all you need to know.

Resources