Do I need to enable authentication for MongoDB? - node.js

I've just set up MongoDB, got a hold of mongoose as well and while I was following some tutorial of connecting to the database I have noticed that there's no user/password being required by default which lead me to the following question:
Is that a security issue when moving to production? What security measures do I need to take? Would anyone be able to access MongoDB remotely? How to suppress that if so.

Indeed, You have stumbled upon a valid question.
You check out this source:
http://mongodb.github.io/node-mongodb-native/contents.html
And have a code which does something of this sort:
var Db = require('mongodb').Db,
MongoClient = require('mongodb').MongoClient,
BSON = require('mongodb').pure().BSON,
assert = require('assert');
var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
{auto_reconnect: false, poolSize: 4}), {w:0, native_parser: false});
// Establish connection to db
db.open(function(err, db) {
assert.equal(null, err);
// Add a user to the database
db.addUser('user', 'name', function(err, result) {
assert.equal(null, err);
// Authenticate
db.authenticate('user', 'name', function(err, result) {
assert.equal(true, result);
db.close();
});
});
});
Just adding a few more sources you might want to have a look at:
https://docs.mongodb.org/v3.0/administration/security-checklist/
https://docs.mongodb.org/manual/administration/security/
Hope this is a good starting point in your quest for productionizing MongoDB!

Yes it is problematic if access is possible from the internet (i.e., is not firewalled, has a weak/no password, or not bound to localhost only). Attackers might be easily able to access your DB and read all data. This is not just a theoretical threat, see http://www.cso.com.au/article/566040/students-find-40k-unprotected-mongodb-databases-8-million-telco-customer-records-exposed/ for a recent "indicent".
The mongodb developers provide a security checklist and also provide a security tutorial.
So, at least set a password and at best bind it to localhost only (also problematic if other users also have access to that machine) in order to prevent brute force attacks.

Security should be a multi-layered approach.
First of all, in production, I would recommend putting MongoDB on a separate physical machine.
I would restrict access to this machine via the firewall, such that only MongoDB traffic on port 27017 can access the MongoDB machine from the webservers.
I would only allow ssh access to the MongoDB machine or the webservers from specific IP addresses which need access to them.
I would use only key-based authentication for SSH to both the Webservers and MongoDB machine.
I would completely block the MongoDB machine from accessing the internet, aside from NTP for time synchronization.
Although I feel the above steps are more important, I would enable MongoDB authentication.
This is a weak layer of security, though, since only the webservers should be able to access port 27017 on the MongoDB machine, and anyone who compromised the webserver would be able to extract the MongoDB password from the source code on the server.
If you have multiple MongoDB databases, you can use different authentication credentials for each database, to add a level of isolation between applications.
In short, no, you don't need authentication, but it can add an extra layer of security. The other layers are far more important.

Related

Querying my Cloud Sql DB from my Node.js backend

Recently I've been learning google cloud sql it took a little but I was able to connect my cloud sql auth proxy to my postgres client. However I'm not sure how to query or make post request to my cloud sql. Originally I was just doing
const Pool = require("pg").Pool;
const pool = new Pool({
user: "postgres",
password: "****",
host: "localhost",
port: 5432,
database: "somedb"
});
I'm not sure how to convert this over to try and query the cloud sql db. I did try converting it and got.
const Pool = require("pg").Pool;
const pool = new Pool({
user: "postgres",
password: "****",
host: "[cloud sql ip]",
port: 5432,
database: "[pg/gc db]"
});
I end up getting the error [pg_hba.conf rejects connection for host "[ipv4 ip]", user "postgres", database "[pg/gc db]", no encryption]. I know that the documentation has a code sample but I don't understand it and cant really find any resources on explaining it.
Edit: I am uploading files to a bucket in cloud storage which I was successfully able to do. I plan on mapping out all these files onto a webpage. However I would like to filter them by certain features so I am making a second request after I store the file. My second request will store attributes into a database that I can then relate to the files for filtering.
If you're running the auth proxy from your local machine where you're running your application, then the code will be the same from your application's code perspective. You'll still connect to localhost (although you may need to connect to 127.0.0.1 depending on how you have hosts set up on the machine).
The database field will depend on how you've set up the database in Cloud SQL, but it should be the same as your local database. E.g. if you created a database named "somedb" in Cloud SQL, you don't have to change anything to connect to it in Cloud SQL. The proxy running locally will make everything behave as if you're running the database locally from the application's perspective.
Edit: This particular answer wasn't the issue they were having, but in the comments it came up that both the Proxy and SSL-only was being used, which is (generally) less recommended as it doubles up the SSL/TLS usage because the Proxy also uses generated SSL certificates to connect to Cloud SQL so the database-level SSL connectivity is a redundancy that's likely not needed. There are some edge cases where you may want both, but broadly speaking one or the other is recommended.

How to properly setup Heroku Node.js Connection to Heroku-Postgres when sql_error_code = 28000 (no pg_hba.conf entry for host) occurs

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?

Connecting to managed redis with auth username/password nodejs

Edit: After thinking about the issue, the real question is what is an example of connecting to digitalocean's managed redis with node-redis using tls?
I'm able to connect just fine with redisinsight GUI client using username / password, but cannot connect with nodejs. It's on the same computer so no firewall issues.
var redis = require('redis');
var client = redis.createClient(process.env.REDIS_PORT, process.env.REDIS_URL, {no_ready_check: true});
client.auth('password', function (err) {
if (err) {
console.log(err);
return
}
console.log('auth')
});
One thing I'm confused about is where to enter the username? It's just 'default' but the documentation for node_redis doesn't provide a way to give a username during auth.
Error is: AbortError: Redis connection lost and command aborted. It might have been processed.
Here's my working lightly anonymized redisinsight connection screen.
How do I do the same in node-redis?
The AUTH command, as stated in the docs:
When ACLs are used, the single argument form of the command,
where only the password is specified, assumes that the implicit username is "default".
So even if you are using Redis 6, where additional users are supported, your authentication for default should work.
The error you're seeing is the result of a broken connection, e.g. you somehow lost connection with the Redis server. node-redis is dealing with one of two scenarios (or both) - the connection has timed out or the the reconnect attempts have exceeded the maximum number specified in a config. I would double check your connection information and how your redis server is configured.
I see you are using TLS, you may find this useful: Securing Node Redis
If you want to authenticate node-redis client with a different user, when using Redis 6, you will have to use send_command, but before you need to remove the current AUTH command, as currently node-redis doesn't support the new command AUTH <username> <password>.
client['auth'] = null;
client.send_command('AUTH', ['<username>', '<password>'], redis.print);

node-postgres pool management

I'm trying to connect Nodejs to PostgreSQL database, for that I'm using node-postgres.
var pool = new Pool({
user: username,
password: password,
host: server
database: database,
max: 25
});
module.exports = {
execute_query: function (query2) {
//usage of query
pool.query('query2', function(err, result){
return (result);
});
}
};
Then in my application, the function execute_query is called in different places in the application.
Locally it works but I wonder how the pool is managed, is this enough configuration to manage concurrent users if my application is used by different people ?
Do I need to do anything else to ensure that I have clients in the pool ?
Or should I use the old way of managing clients with a hard code ?
I read the documentation of node-postgres and it says that pool.query is the simplist way but it doesnt say how it manages the connections...
Do you have any information ?
Thank you
is this enough configuration to manage concurrent users if my
application is used by different people ?
This is a very broad question and depends on more than one thing. Let me still give this a shot
Number of connection in the pool is the number of active connections your server will maintain with the db. Each connection as a cost as postgres maintains this as a separate process. So just focussing on the connection pool is not enough.
pgtune gives you a good recommendation on your postgresql.conf setting based on your hardware.
If you want to test out your application, you can test using jMeter or any other load testing tool to see how your application will perform under certain load.
Some good resources to read on the topic stack overflow answer, postgres wiki

What's the proper way of using Postgres connections in Node?

I was wondering if anyone can help me understand what the proper way of maintaining multiple connections to multiple postgres servers via https://github.com/brianc/node-postgres is.
Obviously when running a node server for long duration we want to make sure we keep everything clean with no leaks and so I am wondering what the proper pattern is.
Please remember that my Node server will need to connect to 7-8 Postgres servers.
https://github.com/brianc/node-postgres supports the idea of pools. I am wondering: do I just connect to all servers on initial Node server set up and maintain open connections and each function can ask for a pool when it needs to talk to a server?
In other words, am I supposed to call pg.connect every time I make a server query? (minus the var pg and var connectionString which could be global)
Can't I just have a single connection be on and ready?
var pg = require('pg');
var connectionString = "pg://brian:1234#localhost/postgres"
pg.connect(connectionString, function(err, client, done) {
client.query('SELECT name FROM users WHERE email = $1', ['brian#example.com'], function(err, result) {
assert.equal('brianc', result.rows[0].name);
done();
});
});
Code snippets are greatly appreciated.

Resources