Retrieve environment wise database configurations without revealing it

Pravin Lolage
Pravin Lolage
Published in
4 min readSep 29, 2018

Why Database configuration should not be stored in the application?

In most of today's nodejs applications, we have seen that database configuration is stored in the json file inside the application. We have also seen that environment-wise database configuration is maintained to access a particular database as per the environment e.g. development.json will have database configuration which will be run on a development environment.

Even these configurations are git ignored, it can be easily vulnerable by the users who have the right code access and also it’s a big headache to maintain it in different environments. So it’s really necessary to avoid this vulnerability by maintaining configurations in an encrypted way.

Let’s check it out, how can we access this environment wise configurations in a secure way.

Maintain a single master database

We need to maintain a single master database for storing these configurations in an encrypted format and can be accessed using a key. In my case, I am using PostgreSQL which provides the `pgcrypto` extension for cryptography.

Note: Even if master database is accessible inside the code, no one will be able to decrypt your configurations without encryption key.

So let’s create a database:

-- create database
CREATE DATABASE master_db_config;

Now, let’s have a table to store configurations:

-- create table
CREATE TABLE app_config(
id SERIAL PRIMARY KEY, -- auto increment id
config bytea, -- encrypted config
env varchar(30), -- environment e.g. dev
project_key varchar(30), -- unique project key
is_active bool default true,
createdon timestamp,
updatedon timestamp
);

Here, id represents the auto increment id, config is the encrypted data column, env can be development, test, production, etc. project_key is a unique project identifier.

Now, let’s activate the `pgcrypto` extension using:

-- this is required for running encrypt and decrypt functions
CREATE EXTENSION pgcrypto;

Let’s insert our first config for the development environment:

INSERT INTO app_config(config, env, project_key, createdon, updatedon) VALUES ( encrypt( '{"host":"localhost","port":"5432","database":"myDb","user":"postgres","password":"root","max":"10","idleTimeoutMillis":"30000"}', 'ml9gi2r5ce275y3i8sxq', 'aes'), 'development', 'MY_WORST_PROJECT', '2018-09-29 10:01:00', '2018-09-29 10:01:00' );

So if you check this insert query, encrypt function is passed as value and JSON config is given as an argument to it. `ml9gi2r5ce275y3i8sxq` is the key to encrypt the config, you can pass any random string to encrypt it. aes is the encryption algorithm.

Note: You need to store this key somewhere safely as you won’t be decrypt your config without key.

Here we finish our master DB setting. So let’s move on to the code.

Let’s code it

I have created the library for easily accessing your configurations form Postgres, so, first of all, add it to your node modules using the following command:

npm install --save https://github.com/pravindot17/configprovider

Now you have this as a module, so let’s use it in your application

let configProvider = require('configprovider');

let masterDbConfig = {
"host":"localhost",
"port":"5432",
"database":"master_db_config",
"user":"postgres",
"password":"root",
"max":"10",
"idleTimeoutMillis":"30000"
}

// init the connection in your bootstrap file using following code
configProvider.init(masterDbConfig, 'MY_SECRET_KEY', 'development', 'MY_WORST_PROJECT').then((appConfig) => {
console.log('received the db config here in appConfig.dbConfig');
}).catch(console.error);

MY_SECRET_KEY: This is the secret key that was used while inserting the database configuration in master DB. We can provide this key in node ENV during deployment or running your application. e.g. If you are running your application in development we can pass DB_KEY=’MY_SECRET_KEY’ in npm start command as below:

NODE_ENV="development" DB_KEY="MY_SECRET_KEY" node app.js

And access it in your code using process.env.NODE_ENV and process.env.DB_KEY

In this way, we will get our database configuration in our bootstrap file mostly app.js. To use it anywhere in the application, just use:

// to use it inside your application use following
let dbConfig = configProvider.getConfig().dbConfig;

Note: This library is using module caching so every time we require this library in application, it’s not going to hit master database except in bootstrap file where init function is called.

I have also added some functions so that existing application configuration can be added to it, so that the entire application and database configuration will be easily accessible across the application.

// You can also add more config to the cache
configProvider.addConfig('appConfig', {"title": "My worst application", "isEmailRequired": true});
// You can also merge config into existing config
configProvider.mergeConfig({"smsConfig": { "isEnabled": true, "content": "Have a good day!" }});

Conclusion

In this way, we can retrieve our database configurations easily without compromising our database connections.

Thanks for reading!

If you like the above article please clap the same and if you don’t like please put your thoughts in comments so that I can improve it.

You can reach me out on Linkedin, Quora.

--

--

Pravin Lolage
Pravin Lolage

A software enthusiast with almost 8+ years of experience in programming trying to share my knowledge.