elency-config is a http application
built on the node.js
platform to provide configuration management for multi-tenant applications hosted on any platform.
- Prerequisites
- Install
- Configuration
- MongoDb
- How does it work?
- Security
- Ping endpoint
- Health endpoint
- Users/Roles
- LDAP
- Keys
- Configuration Data
- License
This document assumes you will be installing elency-config
on a linux
based system.
elency-config is built with nodejs and has the following dependencies.
- nodejs, the minimum supported
LTS
version is8.9.0
. - mongoDB, the minimum supported version is
3.0
. It ishighly
recommended that the mongo server being connected to is locked down and requires credentials.
This document assumes you will be installing elency-config
on a linux
based system.
The server should be setup with a reverse proxy
in front of it over https
and using valid SSL certificates
.
-
Download elency-config-server.
-
Extract the above
tar.gz
file into a desired location on your machine.tar xzf ./elency-config-server-0.0.22-beta.tar.gz
-
Create and add the relevant config and security files to the
config
andsec
directories. Refer to the Configuration section. -
Run the application
Execute the
start
script this will expose a node/express app on port3000
. The port can be overriden by executing with aPORT
environment variable.The start script installs
PM2
and also sets up aservice
../start
-
Stopping the application
Execute the
stop script
./stop
If you would like to run the server in a docker containerised environment you can make use of docker images.
Docker images exist for the server but as it is dependent on configuration data. Refer to the Configuration section.
Retrieval of configuration data to be injected into containers should be carried out following your company guidelines. Please refer to the security section about storage of secure information.
Firstly within a directory you will need a docker-compose.yml
which contains some of the following yml:
version: '3'
services:
app:
container_name: elency-config-server
image: croweman/elency-config-server:0.0.22-beta
restart: "on-failure:10"
volumes:
- ./configuration_files:/app/configuration_files
ports:
- "3000:3000"
environment:
CONFIG_JSON_VALUE:
KEYS_JSON_VALUE:
PRIVATE_PEM_VALUE:
PUBLIC_PEM_VALUE:
Configuration can be injected into the container in either of the following 2 ways.
In a directory create a local configuration_files
directory and copy the 4 configuration files into it at the root.
To bring up the container execute.
docker-compose up
You would need to read the relevant configuration values into environment variables and inject them into the container when bringing it up
CONFIG_JSON_VALUE=`cat ./config.json`
KEYS_JSON_VALUE=`cat ./keys.json`
PRIVATE_PEM_VALUE=`cat ./elency-config.private.pem`
PUBLIC_PEM_VALUE=`cat ./elency-config.public.pem`
rm ./config.json
rm ./keys.json
rm ./elency-config.private.pem
rm ./elency-config.public.pem
CONFIG_JSON_VALUE=$CONFIG_JSON_VALUE KEYS_JSON_VALUE=$KEYS_JSON_VALUE PRIVATE_PEM_VALUE=$PRIVATE_PEM_VALUE PUBLIC_PEM_VALUE=$PUBLIC_PEM_VALUE docker-compose up
The server is dependent on 4 configuration files. These files and content (encrypted/decrypted) should be stored securely following your company guidelines. Please refer to the security section about storage of secure information.
-
You will need to generate a
public
andprivate
key pair.This key pair will be used to encrypt/decrypt configuration files and some mongo data.
These files should live within the
sec
folder.cd ./elency-config-server openssl genrsa -out ./sec/elency-config.private.pem 2048 openssl rsa -in ./sec/elency-config.private.pem -outform PEM -pubout -out ./sec/elency-config.public.pem
-
Create
config.json
configuration file.Create a
config.json
file within theconfig
folder and update its settings!If running
locally
orproxied
(overhttp
, nothttps
) the UI routes will not work ifrunOverHttp
has a value offalse
, you will need to change this totrue
!{ "mongoUrl": "mongodb://localhost:27017/elency-config", "HMACAuthorizationKey": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "exposeUIRoutes": true, "maxJsonPostSize": "1mb", "runOverHttp": false, "sessionLifeTimeInMinutes": 20160, "validateAuthorizationTokenWindow": true, "authorizationTokenValidationWindowInSeconds": 300 }
mongoUrl
: Defines the mongo url, it is recommended you use credentials and lock down the mongo db.HMACAuthorizationKey
: This is the key used for creating authorization headers. It should be a32
characterbase64
encoding string.exposeUIRoutes
: (default: false) Defines whether the admin interface should be exposed.maxJsonPostSize
: (default:1mb
) Defines the max payload size that can be posted.runOverHttp
: (default: false) Defines whether the web application is running over http (not https) and should create non secure cookies.sessionLifeTimeInMinutes
: (default: 20160 (14 days)) Defines the life time of a session cookie.validateAuthorizationTokenWindow
: (default: false) Defines whether the authorization token timestamp should be validated.authorizationTokenValidationWindowInSeconds
: (default: 300) Defines the authorization token validation window in seconds.
-
Create
keys.json
configuration file.Create a
keys.jon
file within theconfig folder
and update its settings!{ "configEncryptionKey": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" }
configEncryptionKey
: This is the key used for some encryption. It should be a32
characterbase64
encoding string.
-
run the
encrypt-configuration-files
toolExecute either the node or bash
encrypt-configuration-files
tool to encrypt and decrypt the configuration files (config.json
andkeys.json
).node:
// encrypt node ./encrypt-configuration-files.js // decrypt node ./encrypt-configuration-files.js -d
The file can be found here.
The data storage mechanism used is mongoDB. elency-config is dependent on a number of collections and indexes.
If the connection string you are using is locked down to a specific account and this account does not have permissions to create indexes then these will have to be manually created!
Index definitions can be found here.
The server
provides a REST API
for retrieving configuration data for a team/application. It also optionally
provides a Web UI for administering various data.
Essentially clients
are used and configured to connect to the REST API
and utilise access tokens
and decryption keys
. These clients will request configuration data from a server based on an appId
, environment
and version
e.g. 1.0.0
.
The server
will process the following rules to determine what configuration (if any) should be returned:
- The configuration is
published
. - the
configuration version
isless than or equal to
the givenversion
. - the
configuration version
returned is the highest of all matches of the above criteria. - the
configuration
returned is the most recent revision of the above criteria.
The server
allows you to configure many things, some of which are the following:
- Teams
- Applications
- Environments
- Users (Optionally LDAP)
- Permissions
- Configuration Data
- Keys
The best way to see how it works
is to have a play
.
The server
stores all of its data with in a mongo database, some of which is hashed
or encrypted
.
When installing the server
, setting up the admin
user or creating any keys
, it is recommended you store sensitive
data and the .pem key files
, keys
and configuration files
securely following your company guidelines. As you may need to recover them following a failure.
The following recommendations are advised:
-
The
mongoDB
server being connected to should be locked down to require credentials in the connection string. These would be configured in theconfig.json
file which will be encrypted. -
The
server
should be exposed overhttps
for secure communication of sensitive data. ValidSSL certificates
should be used. -
All types of
keys
shouldnot
be stored incode bases
orsource control
providers. -
When creating
configuration
entries anyentries
that potentially containsecure
data should be marked asSecure
. These are encrypted and will need to be decrypted by clients. -
Clients that consume the server
REST API
and make use ofHMAC Authorization
andConfiguration Encryption
keys should retrieve thekeys
following best practises andnot
be stored in code bases.
A ping endpoint is provided so that you can determine whether the application is up and exposing routes e.g. http://address/private/ping.
The endpoint will return a 200
status code and a pong
in the response.
A health endpoint is provided so that you can determine whether the application is up and exposing routes but also healthy
e.g. http://address/private/health.
The endpoint will return a 200
status code if the application is healthy.
On the initial first run of the server
you will have to setup a password for the admin
user. This user has permissions to:
- Create users
- Edit users
- Change passwords.
The following roles are available for a user:
administrator
: Can create/edit users, change settings, create teams, create keys.team-writer
: Can create teams and apps.key-writer
: Can create keys.
Additional roles can be created.
Setting permissions to be able to create applications
, environments
and configuration
is configured per user/role
.
These permissions may be set per team
or per app
and will be to:
- Read
- Write
- Publish
LDAP security can be configured by an administrator
by configuring Settings
.
When creating environments
they will need a key
associated with them.
Keys can be created through the admin ui.
When editing a key
. Its value can be decrypted by having access to the elency-config.private.pem
file.
Keys should be 32
character base64
encoded strings.
These can be generated through the ui
or by using key-generator.js.
Configuration is stored under a applications configured environment.
An application environment can have many configurations associated with it.
Configuration data is stored in key value pairs and can be encrypted.
The validity of configuration data can be optionally
enforced through JSON Schemas
which can be configured at application
or application environment
level.
If a JSON Schema
is configured at both application
and application environment
level then the application environment
JSON Schema takes precidence.
An example JSON Schema
may look like this:
{
"properties": {
"LOG_LEVEL": {
"type": "string",
"enum": ["info", "debug", "warn", "error", "fatal"]
},
"MONGODB_URL": {
"type": "string",
"minLength": 1,
"secure": true
}
},
"required": [
"LOG_LEVEL",
"MONGODB_URL"
]
}
"secure": true
indicates that the property must be marked as Encrypted
in the admin UI.
(The MIT License)
Copyright (c) 2020 Lee Crowe
a.k.a. croweman
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.