So it took me a bit to set up a repl set with SSL and authorization. However, I have it set up and working finally, and can connect via command line providing the appropriate parameters. I'm trying to do the same thing with mongoose, however I keep getting an error in the mongodb logs, as follows: AssertionException handling request, closing client connection: 17189 The server is configured to only allow SSL connections Even though I specified all the ssl options.
My code is as follows:
var m = require('mongoose');
var key = fs.readFileSync('/home/node/mongodb/mongodb.pem');
var ca = [fs.readFileSync('/home/node/mongodb/ca.pem')];
var o = {
server: {
sslValidate:true,
sslCA: ca,
sslKey: key,
sslCert:key
},
user: '****',
pass: '****'
};
m.connect('mongodb://dbAddr/dbName', o)
I've tried setting sslValidate to false, same issue. I've tried without CA, cert, and/or key in multiple combinations. When I connect via command line it requires me to provide CA, and key+cert PEM file. So I figured the mongoose client would require these as well. I've tried both server and replset keys with the same exact outcome. I've even specified authSource(authDB), even though it appears this is not part of the problem, this still yields the same results.
I'm really confused especially since I have no problem doing this exact same thing via the mongo command.
My mongo shell command is as follows:
mongo --host db1 --ssl --sslPEMKeyFile /etc/mongodb/mongodb.pem --sslCAFile /etc/mongodb/ca.pem -u *** -p *** --authenticationDatabase dbName
Not depicted in the mongoDB node driver documentation, you must also provide the option {server: {ssl: true} in order to connect via SSL. If you do not, the other options are simple ignored.
However, if you dig into the mongoose issue tracker on github you'll find this, which recommends this exactly.
Related
I'm trying to figure out how to set up my backend api (next.js/api) to the database (postgresql) that both are hosted by heroku.
Mediated by pg.pool, i set up with the following code.
const pool = new Pool(
{
connectionString: process.env.DATABASE_URL,
// ssl: {
// rejectUnauthorized: false,
// }
})
but returned by heroku with the following error:
sql_error_code = 28000 FATAL: no pg_hba.conf entry for host "122.180.247.11", user "u3idolso5k2v83", database "dc85788d13v9ej", SSL off
The error description is from:
https://help.heroku.com/DR0TTWWD/seeing-fatal-no-pg_hba-conf-entry-errors-in-postgres
EDIT: meant to post this link, Is it ok to be setting rejectUnauthorized to false in production PostgreSQL connections?
The authentication failed because the connection didn't use SSL encryption: (SSL off). All Heroku Postgres production databases require using SSL connections to ensure that communications between applications and the database remain secure. If your client is not using SSL to connect to your database, you would see these errors even if you're using the right credentials to connect to it.
I find this strange, since heroku do provide ssl already to my server hoested by them by default, so its unexpected for such an error to occur at all?
The side step solution I've come across online is uncomment the ssl property in the connection...which works, but i feel uneasy with this one.
const pool = new Pool(
{
connectionString: process.env.DATABASE_URL,
ssl: {
rejectUnauthorized: false,
}
})
As mentioned briefly it is not safe from here: https://security.stackexchange.com/questions/229282/is-it-safe-to-set-rejectunauthorized-to-false-when-using-herokus-postgres-datab
I don't understand why this error occur at all, and how can it be fixed with proper security.
It's pretty standard for SSL certificates for Postgres servers to not be valid. Even official postgres clients don't validate the certificates. The library you are using defaults to validating certificates, but is very much in the minority.
When setting this up for https://www.atdatabases.org/docs/pg-options I made it not validate certificates by default to match the standard behaviour for Postgres.
This lets you create a connection pool for heroku using simply:
import createConnectionPool from '#databases/pg';
createConnectionPool(process.env.DATABASE_URL);
As described in your linked-to answer, you can upgrade to one of Heroku's paid products which does support this. Or you can stop using Heroku. Or you can put up with the incredibly low risk that someone will MITM you.
I don't understand why this error occur at all,
What about it do you not understand? The explanation you linked to seems pretty clear. If you cannot formulate your uncertainty any more clearly than you have so far, how can anyone help you understand?
We recently moved to Heroku and upon attempting to connect our apps to the DB, it kept rejecting our queries with the message "Self signed certificate". Passing in rejectUnauthorized solved for this but now I'm wondering, should we be doing this in production? If not, what is the appropriate way for us to be connecting to our Heroku PG Databases?
const pgp = require('pg-promise')(/*initOptions*/);
const {ConnectionString} = require('connection-string');
const cnObj = new ConnectionString(process.env.DATABASE_URL);
const cn = {
host: cnObj.hostname,
port: cnObj.port,
database: cnObj.path?.[0],
user: cnObj.user,
password: cnObj.password,
ssl: {
rejectUnauthorized: false,
},
};
const db = pgp(cn);
The risk you are running is that somebody gets between you and the Heroku server and impersonates the latter. They can then present their own certificate to you and negotiate a connection with you. The man in the middle can also pass the challenge from the server down to you and use your response to log into the database server in your stead.
All that assumes that the attacker has control over one of the network nodes between you and the Heroku server.
So I would say that while there is a residual risk, I wouldn't lose too much sleep over it, unless you are working with really sensitive data, in which case paranoia is a virtue.
I have a Redis server running with Node.JS version 10.4.2. I am using the NPM "redis" client with my app. I am using the following code to create the Redis client and to authenticate. (Note the code commented out below to see what else I tried):
var redis = require("redis");
// var redisClient = require('redis').createClient(process.env.REDIS_URL || redis);
var redisClient = redis.createClient(
{
port: process.env.REDIS_PORT,
host: process.env.REDIS_URL,
no_ready_check: true,
auth_pass: process.env.REDIS_AUTH
});
/*
// Authenticate with Redis.
redisClient.auth(process.env.REDIS_AUTH, function(err, reply) {
if (err) {
console.error(err);
}
else {
console.log(reply);
}
});
*/
However, I always get the error below:
ReplyError: ERR invalid password
When I used the code that is commented out, I did not use the "no_ready_check" property during createClient(). Some facts:
I triple-checked the value in process.env.REDIS_AUTH and it matches exactly what is in my Redis server conf file for the requirepass password value.
I can use the password to successfully authenticate when testing with the Redis command line client (redis-cli) so I know the Redis server is password protected and that the password works.
I know the password is getting through because when I use the code that is commented out, I can see the correct password in the arguments passed to the callback function.
Why isn't my password working with my Node.JS code and how can I fix this? Note, the password was generated using the SSL random password generator on Linux. I mention that in case it affects anything.
UPDATE: I got this working by using a much shorter password in the Redis server conf file. Apparently the Node.JS Redis package doesn't like the long random passwords generated by the Linux SSL utility, despite there being no strange characters in those passwords at all. I posted an issue on this subject on the package repo here:
https://github.com/NodeRedis/node_redis/issues/1411
I was using the following commands to create the password using OpenSSL on my Linux box:
openssl rand 60 | openssl base64 -A
Unfortunately openssl creates passwords with forward slashes in them "/". There may be other characters that are not healthy in this context, but I have not exhaustively tested them. Once I removed the forward slashes from the password, and after I restarted Redis server to register the changes, the client creation attempt worked from Node.JS.
Something is happening on the Node.JS side to those characters on the way to Redis. As I said, I had no problems when directly pasting the very same forward slash containing passwords into the Redis client when using the auth command. But using them from Node.JS causes the authentication attempt to fail.
My best advice to anyone reading this post is if you are using the openssl command to generate redis passwords for your Node.JS app, remove any characters are that are not strictly 'a-zA-Z' from the generated password. Perhaps someone will give a better solution later as a reply.
I am learning NodeJS by building a JWT server. Basically I want to authorize users against credentials in a PostgreSQL database. I am considering node-postgres, passport, pg to connect with PostgreSQL but I have not found anyway to store my connection values encrypted. Ideally I would store them in a properties file so I can change them per environment.
Most examples I see do something like:
var pg = require('pg');
var conString = "postgres://YourUserName:YourPassword#localhost:5432/YourDatabase";
Can someone help show me how to encrypt and use my credentials so I don't have to hard code the plain values in my source?
There seem to exist npm packages for this already. See https://www.npmjs.com/package/secure-conf. Seems to fulfill your needs.
Please note, that you should also secure your Connection to the DB using SSL. See SSL for PostgreSQL connection nodejs for a Solution.
This should help.
if you use sequelize to connect postgres
const sequelize = new Sequelize("DB", usrname, password, {
host: "/var/run/postgresql",
dialect: "postgres",
});
NB: get the host string from your pgsl db might be different //
When I tried to use adapter: 'redis' it told me to install socket.io-redis version 0.14. I did that and have entered in all the info into the session.js file:
module.exports.session = {
adapter: 'socket.io-redis'
host: '10...',
port: 6379,
db: 'sails',
pass: '...',
};
And now when I try run the application I get the following error:
Error: Ready check failed: NOAUTH Authentication required.
I'm not sure why pass: .. is not working? Anything else I should do?
Note: I am using a Google compute instance for redis hosting, I have a firewall rule for allowing access.
I did find a solution for my problem. I am not sure how useful it will be for you, since I believe my situation was a little different. I am using sails.js on a bitnami Google cloud compute instance and I am also hosting redis on a seperate bitnami instance, which we have in common. However, I am trying to connect to Redis for the use of Kue. So I did not make any use of my config/session file. We still got the same error though, so the solution was to remove the requiredpass in the redis instance and then with the firewall rules, only allow my server to access the Redis instance.
I believe the root issue is that redis has a second password prompt for any attempt to read/write to data store. So passing the password from the server only logs you in but does not give you access to the data, hense the NOAUTH error. So I believe the requiredpass for the instance is mainly for the client side and server side instances don't need it. This might be me being naive on how to use Redis, but I do not know how else to enter the password to the prompt from a different server. I feel the firewall rules are fine for me for now to keep unwanted traffic out.
If this is what you want to do/try, then the way I did this for Google cloud was ssh into the Redis instance (through your own command line or through the browser one that Google provides. Then edit the /opt/bitnami/redis/etc/redis.conf file with sudo privileges. Find the line that says requiredpass and comment that out by placing a # in front of it. Now to get this to take affect, then you have to restart the server.
Bitnami says you can just do this with sudo /opt/bitnami/ctlscript.sh restart redis. However, I was getting an AUTH error. So in order to get around that, I had to force kill the proccess with sudo pkill -9 -f redis-server, then restart it with sudo /opt/bitnami/ctlscript.sh restart redis. This should refresh the config file, update the instance and allow your server to connect without requiring a second prompt password to be entered.
If you have any questions, please let me know and I will try to help as much as possible.
You have to specify auth_pass:
module.exports.session = {
adapter: 'socket.io-redis'
host: '10...',
port: 6379,
db: 'sails',
pass: '...',
auth_pass: redis_url.auth.split(":")[1]
};
UPDATE
From documentation:
password: null; If set, client will run redis auth command on connect.
Alias auth_pass (node_redis < 2.5 have to use auth_pass)