Почему конфигурацию базы данных не следует хранить в приложении?

Мы видели, что в большинстве современных приложений nodejs конфигурация базы данных хранится в файле json внутри приложения. Мы также видели, что конфигурация базы данных с учетом среды поддерживается для доступа к конкретной базе данных в соответствии со средой, например. development.json будет иметь конфигурацию базы данных, которая будет запускаться в среде разработки.

Даже эти конфигурации игнорируются git, они могут быть легко уязвимы для пользователей, у которых есть правильный доступ к коду, а также большой головной болью поддерживать его в разных средах. Поэтому действительно необходимо избежать этой уязвимости, сохраняя конфигурации в зашифрованном виде.

Давайте посмотрим, как мы можем получить безопасный доступ к этим конфигурациям среды.

Поддерживайте единую главную базу данных

Нам необходимо поддерживать единую главную базу данных для хранения этих конфигураций в зашифрованном формате, доступ к которой можно получить с помощью ключа. В моем случае я использую PostgreSQL, который предоставляет расширение pgcrypto для криптографии.

Примечание. Даже если основная база данных доступна внутри кода, никто не сможет расшифровать ваши конфигурации без ключа шифрования.

Итак, давайте создадим базу данных:

-- create database
CREATE DATABASE master_db_config;

Теперь у нас есть таблица для хранения конфигураций:

-- 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
);

Здесь id представляет идентификатор автоматического увеличения, config - столбец зашифрованных данных, env может быть для разработки, тестирования, производства и т. Д. project_key - уникальный идентификатор проекта.

Теперь давайте активируем расширение pgcrypto, используя:

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

Давайте вставим нашу первую конфигурацию для среды разработки:

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' );

Поэтому, если вы проверите этот запрос на вставку, функция шифрования передается как значение, а конфигурация JSON предоставляется в качестве аргумента для нее. ml9gi2r5ce275y3i8sxq - ключ для шифрования конфигурации, вы можете передать любую случайную строку, чтобы зашифровать ее. aes - алгоритм шифрования.

Примечание: вам нужно где-то надежно хранить этот ключ, так как вы не сможете расшифровать конфигурацию без ключа.

На этом мы завершаем настройку нашей основной БД. Итак, перейдем к коду.

Давайте закодируем

Я создал библиотеку для легкого доступа к вашим конфигурациям из Postgres, поэтому, прежде всего, добавьте ее в свои модули узлов, используя следующую команду:

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

Теперь у вас есть этот модуль, так что давайте использовать его в своем приложении.

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: это секретный ключ, который использовался при вставке конфигурации базы данных в главную БД. Мы можем предоставить этот ключ в узле ENV во время развертывания или запуска вашего приложения. например Если вы запускаете свое приложение в разработке, мы можем передать DB_KEY = ’MY_SECRET_KEY’ в команде запуска npm, как показано ниже:

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

И получите доступ к нему в своем коде, используя process.env.NODE_ENV и process.env.DB_KEY

Таким образом, мы получим конфигурацию нашей базы данных в нашем файле начальной загрузки, в основном app.js. Чтобы использовать его в любом месте приложения, просто используйте:

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

Примечание. Эта библиотека использует кеширование модулей, поэтому каждый раз, когда нам требуется эта библиотека в приложении, она не будет попадать в основную базу данных, за исключением файла начальной загрузки, в котором вызывается функция init.

Я также добавил некоторые функции, чтобы к нему можно было добавить существующую конфигурацию приложения, чтобы все приложение и конфигурация базы данных были легко доступны для всего приложения.

// 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!" }});

Заключение

Таким образом, мы можем легко получить конфигурации нашей базы данных без нарушения наших соединений с базой данных.

Спасибо за прочтение!

Если вам понравилась статья выше, хлопайте в ладоши, а если не нравится, поделитесь своими мыслями в комментариях, чтобы я мог ее улучшить.

Вы можете связаться со мной в Linkedin, Quora.