Before we are looking into the details how to setup a non-anynomous connection to Domino’s Proton server, I have an advice for protecting the key files required for the connection.
The keys are not password protected, and this is a high risk which should be avoided: First, if you make a mistake or if there is a bug in the software, the keys could be accessed from „outside“. And second, if you check in your code in a repository, the IT security should roast you. It’s clear that the keys are still unprotected if someone hacks the application, but this is a different topic.
First thing to to is to encrypt the keys with AES. To achive this, we are using openssl:
openssl enc -aes-256-cbc -k "0123456789" -in domino-express.key -out domino-express.key.enc
The parameter -k is the key to use for encryption. The path to the unencrypted file is passed with -in, and -out is the path of the encrypted file.
I also encryted the .crt files, which is not required, but it does not hurt either.
The config.js file must now be changed to the follwing (a new method for reading and decrypting the files with openssl is added):
const exec = require('child_process').execSync;
const path = require('path');
/**
* reads an aes-256-cbc encrypted file & decrypts it
*
* @param {*} fileName
* the encrpyted file
* @param {*} key
* the decryption key
*/
const readFileEncrypted = (fileName, key) => {
try {
// resolve the filepath
const filePath = path.resolve(fileName);
// use openssl to decrypt the keys
return exec(`openssl enc -d -aes-256-cbc -k "${key}" -in "${filePath}"`,
(error, stdout) => {
if (error) {
console.error(`exec error: ${error}`);
}
return stdout;
});
} catch (error) {
console.error(error);
return undefined;
}
};
// the password (stored in environment)
const password = process.env.PASSWORD_KEYFILES;
if (!password) {
console.error('Environment Variable "PASSWORD_KEYFILES" is not set.');
process.exit(1);
}
// load the keys & certificates
const rootCertificate = readFileEncrypted('./app/certs/ca.crt.enc', password);
const clientCertificate = readFileEncrypted('./app/certs/domino-express.crt.enc', password);
const clientKey = readFileEncrypted('./app/certs/domino-express.key.enc', password);
// check if the keys are ok
if (!rootCertificate || !clientCertificate || !clientKey) {
console.error('Unable to load certificates and/or key.');
process.exit(1);
}
const Config = {
serverConfig: {
hostName: process.env.NODE_ENV === 'development' ? 'dev.example.com' : 'example.com', // Host name of your server
connection: {
port: '3002', // Proton port on your server
secure: true,
},
credentials: {
rootCertificate,
clientCertificate,
clientKey,
},
},
databaseConfig: {
filePath: 'testnode.nsf', // The database file name
}
};
module.exports = Config;
But where to store the key? Nowhere, the key is stored in an evironmental variable.
This line reads the value from the variable PASSWORD_KEYFILES.
const password = process.env.PASSWORD_KEYFILES;
When running your application in a docker container, just start the container with the following command including the variable:
docker run -e "PASSWORD_KEYFILES=0123456789" --name dominoexpress -p 3000:3000 -d -it shasselba/domino-express
To use it in a IDE like Visual Studio Code, you have to add it to the debugging configuration:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Programm starten",
"program": "${workspaceFolder}/app/bin/www",
"env": {"PASSWORD_KEYFILES": "0123456789"}
},
]
}
Now you can add the .enc files to your application in folder /app/certs without worrying about it. If the variable is not set, the application terminates with error code 1.
P.S. Don’t forget to remove the original key files from your project!