diff --git a/README.md b/README.md index 8554891..3e6495d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # README -rdmBuild v2.0 service connector allows for calls into a Multivalue database to return formatted data to the calling end point. This version supports D3, jBase, Universe, QM, and ScarletDME. This is not a complete implentation of the RESTful API Spec. Requests are allowed via both POST and GET to the end point. +rdmBuild v2.3 service connector allows for calls into a Multivalue database to return formatted data to the calling end point. This version supports D3, jBase, Universe, QM, and ScarletDME. This is not a complete implentation of the RESTful API Spec. Requests are allowed via both POST and GET to the end point. The current build supports Linux, AIX, and Windows @@ -45,11 +45,11 @@ Example (depending on our implementation): CREATE-FILE RDM.LIBS 3 11 Copy the install script inside of the mvCode into your favorite terminal emulator. This will create the following subroutines: - RDM.GET.DATA - - A routine to convert any HTTP encoded in your varstring into useable MV arrays + - A routine to convert any HTTP encoded in your varstring into useable MV arrays - RDM.SEND.DATA - - A routine to send back data with the proper `~~START~~` and `~~END~~` tags through rdmBuild + - A routine to send back data with the proper `~~START~~` and `~~END~~` tags through rdmBuild - FORMAT.ERROR - - A routine that accepts a MV array of error messages that will format them in JSON or XML based on the options passed + - A routine that accepts a MV array of error messages that will format them in JSON or XML based on the options passed - **Compile and catalog the above routines** @@ -100,13 +100,13 @@ Using a tool such as Postman (https://www.getpostman.com/) or a web browser hit GET version: -http://YOUR_MULTIVALUE_SERVER:9191/service_name/XML.TEST.CONNCTION/?var=MV%20is%20cool + GET http://YOUR_MULTIVALUE_SERVER:9191/service_name/XML.TEST.CONNCTION/?var=MV%20is%20cool POST version: -POST http://YOUR_MULTIVALUE_SERVER:9191/service_name/XML.TEST.CONNECTION + POST http://YOUR_MULTIVALUE_SERVER:9191/service_name/XML.TEST.CONNECTION -var=MV%20is%20cool + var=MV%20is%20cool ## Response from the XML.TEST.CONNECTION Call (XML or JSON) @@ -115,3 +115,51 @@ var=MV%20is%20cool or (depending on what you send) {"success":"MV is cool"} + +## Basic Authentication + +Make sure the express-basic-auth package is installed. This will allow for basic authentication to be used with the service. + + npm install express-basic-auth + +To use basic authentication, add the following to your server.json file in the configs directory: + + "auth": { + "enable": true, + "users": { + "admin": "pass", + "user": "test" + }, + "challenge": true, + "realm": false + } + +| Key | Description | +| --- | --- | +| enable | Enable or disable basic authentication. | +| users | Object containing username and password pairs. | +| challenge | Enable or disable challenge response. This will cause most browsers to show a popup to enter credentials on unauthorized responses. | +| realm | Set the realm for the challenge response. | + +## SSL Support +To enable SSL support, you will need to update the server.json file in the configs directory to include the ssl section as shown below: + + "ssl": { + "enable": true, + "cert": "server.crt", + "key": "server.key" + } + +| Key | Description | +| --- | --- | +| enable | Enable or disable SSL support. | +| cert | Path to the SSL certificate file. | +| key | Path to the SSL private key file. | + +### Generating Self-Signed SSL Certificates for Testing +You can generate self-signed SSL certificates using OpenSSL for testing purposes. Use the following command: + +```bash +openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' -keyout server.key -out server.crt +``` +Copy both the `server.crt` and `server.key` files to the `certs` directory in your project root and enable SSL in the server.json file as described above. diff --git a/certs/server.crt b/certs/server.crt new file mode 100644 index 0000000..8c1366e --- /dev/null +++ b/certs/server.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDCTCCAfGgAwIBAgIUKAZrYj7UtcsUpmJibV1bu5nu4P8wDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MTIxOTIxMjQ1NVoXDTI2MDEx +ODIxMjQ1NVowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAxnq427Ayw94fxekdlBfIyzOrrvorTUbU2CfEgLAXXhVU +Vji8OC7mMCGLEHCqdOyvEAtunxKaobqBnHBApo5EmmMMGx5wSs/sgLKHOF92PHkv +ImkO5eOn0ifEKqRJc8+JV8XLRAniWA+R9uBVx3qkpHQ9sjkK03EBhI3mzeIGspx/ +ZZhNPMfmDIYOhqzVnl1I84GihnpXpGNhpHCBVHSk5mbE7KHYf4l3opc0U2VQi2D5 +/niQa11+Hi8cCCreiNgstU8EdH1O1bm4S6HabNof+jLfXtCz7cjto0mUDJ0iHhMC +J/5eKSuwIrjVPIn3nP7BHlZ0lWLTLv5zpbmF7+ixrQIDAQABo1MwUTAdBgNVHQ4E +FgQUEv5n6YwQ57+W52k3Vrtt3VloOPswHwYDVR0jBBgwFoAUEv5n6YwQ57+W52k3 +Vrtt3VloOPswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAToWK +MGKX0ATyE4xp5wrZR+AUhOQ5YcT8lm3EgY0a+kvTQX9b0jBrzjI9z4ynHvE2L3UN +U5D0fJbTmj5GSzSdEeyBXF1In4hL/S86aCz63kErKO1aCSp6GbjZS/wpUFer0nFZ +qtCd0RHAIsvr+68Ejhyrw/IZYjufBVG3SqyqymeO6egmv9QY1a2TL6XfwWgPR1Ig +8MFLF0NKH1qNEqZhae9H0d6FzmZXcJsA2M/WtsFS2eL/UWDSxj5ckYNcSCrt6Wgy +vMwBD3s6gnyUqKF+1B6nkbVmOI2Qb8/b6N/1JTc4l9JU3aFZdCQPKY9WipXfl/Qp +VhIRvErtA51rn9pbjQ== +-----END CERTIFICATE----- diff --git a/certs/server.key b/certs/server.key new file mode 100644 index 0000000..5a5cde4 --- /dev/null +++ b/certs/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDGerjbsDLD3h/F +6R2UF8jLM6uu+itNRtTYJ8SAsBdeFVRWOLw4LuYwIYsQcKp07K8QC26fEpqhuoGc +cECmjkSaYwwbHnBKz+yAsoc4X3Y8eS8iaQ7l46fSJ8QqpElzz4lXxctECeJYD5H2 +4FXHeqSkdD2yOQrTcQGEjebN4gaynH9lmE08x+YMhg6GrNWeXUjzgaKGelekY2Gk +cIFUdKTmZsTsodh/iXeilzRTZVCLYPn+eJBrXX4eLxwIKt6I2Cy1TwR0fU7VubhL +odps2h/6Mt9e0LPtyO2jSZQMnSIeEwIn/l4pK7AiuNU8ifec/sEeVnSVYtMu/nOl +uYXv6LGtAgMBAAECggEAHL0xXjIdr6nOnPgbvdFR1EaHkf8MXRSoBiJ//AhDYe6h +txhg/Juh3g9FVRyTOfn5gU++dU8az9czJEVGvzczbM1xt82JAfQocRwoozuDYc9E +SW2/5/62UqJKb8g5EIlZADoWLCRoP0sF3iLumMND6sIgGtnSnPosd5aaeG5FfQAV +Z+fr3DDGHcTg0zSmCd10dr+J/IowwCPezVgNlqpuC4V/iXlR3+ytoYZY8l42oOy0 +v3rWXTTx4cqDiDOR4MtlMTLIMcyBa+VBTg6moEPDkZyv+QIg2PSbMtzrmE0sxLSv +Rt2oIsgJTL3/PReEopHknZDx30D+KVH5NNlIxtiEEQKBgQDJFnCk7Urg9xGjcipR +KhW59c28VSSiSNX1hIwrWnMqWzwcWmEWarYXi28PjUO4vigyp9GwQnJzE+2ZxcqK +MYGp8GSpuP91zKssi16yq56HClm6U6DkYJBwuXsYFnI5amYSl66QtVcPB8o/nPPA +DRyNzg54Wpp0K8MAp+1Caerk+QKBgQD8rfGkV4KtQif2X+KCVg1AgkgzLvgympFg +Rpuss8wSWHY7xeeW0RyMqi7cmqqqBWEXZtlvYWncSECVN+t9Nxs3H2XKmsa/aON1 +OupQgZHSLB8wTSggSsbv0s4pYOHP+wElQqxVkUj3W3QRbsqnkaZcK/D41q//4fPF +JEf22cnDVQKBgDc4Z1STKUXf80MMHdzODstTWd0HEJlUIRVcAdYB77BI/5fVpeWv +BjQvAR+nLlq0NXu7pBSgGqfJaC0bKMSMVcwiDLKi79wciUEhQK8V++GfkQZe4sb0 +UZXzCX+S4mkr873VU4W/lpm1DPAtHK63qwix9j1MvC98uP8cHkZnqa6ZAoGAD3L3 +Lkwncj50QQ0VxVBLmSEeFvsNM9LdhpxqkkGf/ZMpD3iHM2Jvs24IVXajbqfLium/ +655yIYTNZhI4NLy0zkb+K0gRVMyt85H5l5iEeOw3r/VXubm4thsWfdMtm1DGfie4 +b7blVjJiQ1qZy2sNV99b6Wr+8c8331rbh41DV80CgYAYQUwr5aJ9ozUXr8agCWPT +ZvR8WrHx2+ZuNnfAAQPULMlmiUB9PUXg6vZE08/8O/WSVY2bXw2SZaXMZjvCrGW5 +VDdNU6MuuXEn4a6Ah/vmZszE8KZbmXCLoaBc9mcTxFsf6KvsfcyUQfVJBQkWVJ52 +R4ujhouh76fkkoRNeGJ3vQ== +-----END PRIVATE KEY----- diff --git a/configs/server.json b/configs/server.json index b5597ab..5c33aca 100644 --- a/configs/server.json +++ b/configs/server.json @@ -16,5 +16,18 @@ "enable": true, "console": true, "path": "./rdm.log" + }, + "auth": { + "enable": false, + "users": { + "admin": "pass" + }, + "challenge": true, + "realm": false + }, + "ssl": { + "enable": true, + "cert": "server.crt", + "key": "server.key" } } diff --git a/package-lock.json b/package-lock.json index 96351f4..d8fca77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "dependencies": { "axios": "^0.24.0", "express": "^4.17.2", + "express-basic-auth": "^1.2.1", "express-pino-logger": "^7.0.0", "express-queue": "^0.0.13", "express-status-monitor": "^1.3.3", @@ -282,6 +283,22 @@ "node": "^4.5.0 || >= 5.9" } }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -1082,6 +1099,14 @@ "node": ">= 0.10.0" } }, + "node_modules/express-basic-auth": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/express-basic-auth/-/express-basic-auth-1.2.1.tgz", + "integrity": "sha512-L6YQ1wQ/mNjVLAmK3AG1RK6VkokA1BIY6wmiH304Xtt/cLTps40EusZsU1Uop+v9lTDPxdtzbFmdXfFO3KEnwA==", + "dependencies": { + "basic-auth": "^2.0.1" + } + }, "node_modules/express-end": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/express-end/-/express-end-0.0.8.tgz", @@ -3347,6 +3372,21 @@ "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "requires": { + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -4040,6 +4080,14 @@ "vary": "~1.1.2" } }, + "express-basic-auth": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/express-basic-auth/-/express-basic-auth-1.2.1.tgz", + "integrity": "sha512-L6YQ1wQ/mNjVLAmK3AG1RK6VkokA1BIY6wmiH304Xtt/cLTps40EusZsU1Uop+v9lTDPxdtzbFmdXfFO3KEnwA==", + "requires": { + "basic-auth": "^2.0.1" + } + }, "express-end": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/express-end/-/express-end-0.0.8.tgz", diff --git a/package.json b/package.json index 26c2538..d07f455 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "dependencies": { "axios": "^0.24.0", "express": "^4.17.2", + "express-basic-auth": "^1.2.1", "express-pino-logger": "^7.0.0", "express-queue": "^0.0.13", "express-status-monitor": "^1.3.3", diff --git a/riWweb.js b/riWweb.js index 93de4b6..7bba7ef 100644 --- a/riWweb.js +++ b/riWweb.js @@ -77,7 +77,7 @@ app.use("/static", express.static("asset")); // Middleware to process all requests app.use(function(req, res, next) { // Set X-Powered-By header - res.setHeader("X-Powered-By", "RDM Infinity rdmBuild - v2.2"); + res.setHeader("X-Powered-By", "RDM Infinity rdmBuild - v2.3"); // Set the serverConfig to the res.locals object res.locals.serverConfig = serverConfig; @@ -106,11 +106,23 @@ app.use(function(req, res, next) { }); // Start the server -app.listen(serverConfig.server.port, () => { - console.log(`RDM Infinity rdmBuild v2.2 is running on port ${serverConfig.server.port}.`); - if(!logger.enabled && !logger.console) console.log("Server started in silent mode. Logging is disabled."); - if(process.env.watch == 'true') logger.info("Server started in watch mode. Logging to file is disabled."); -}); +if (serverConfig.ssl.enable) { + const certificate = fs.readFileSync(path.join(__dirname, 'certs', serverConfig.ssl.cert), 'utf8'); + const privateKey = fs.readFileSync(path.join(__dirname, 'certs', serverConfig.ssl.key), 'utf8'); + const credentials = { key: privateKey, cert: certificate }; + require('https').createServer(credentials, app).listen(serverConfig.server.port, () => { + console.log(`RDM Infinity rdmBuild v2.3 is running on port ${serverConfig.server.port}.`); + console.log(`SSL is enabled. Using cert: ${serverConfig.ssl.cert} and key: ${serverConfig.ssl.key}`); + if(!logger.enabled && !logger.console) console.log("Server started in silent mode. Logging is disabled."); + if(process.env.watch == 'true') logger.info("Server started in watch mode. Logging to file is disabled."); + }); +} else { + app.listen(serverConfig.server.port, () => { + console.log(`RDM Infinity rdmBuild v2.3 is running on port ${serverConfig.server.port}.`); + if(!logger.enabled && !logger.console) console.log("Server started in silent mode. Logging is disabled."); + if(process.env.watch == 'true') logger.info("Server started in watch mode. Logging to file is disabled."); + }); +} // Route handler for the /plugins endpoint const pluginsDir = path.join(__dirname, 'plugins'); @@ -150,8 +162,26 @@ app.get('/', (req, res, next) => { res.sendFile(path.join(__dirname, 'plugins', 'index.html')); }) +// Check for Basic Authentication +if('auth' in serverConfig && serverConfig.auth.enable && serverConfig.auth.users) { + app.use(require('express-basic-auth')({ + users: serverConfig.auth.users, + challenge: serverConfig.auth.challenge, + realm: serverConfig.auth.realm + })); +} + // Route handler for the MV Database app.use("/:service/:programName/:format?/:debug?", (req, res, next) => { + + // Check program name for special cases + if(req.params.programName == "getAttr") { + req.params.programName = "RDM.GET.ATTR"; + } + + // Convert the program name to uppercase + req.params.programName = req.params.programName.toUpperCase(); + // Extract the parameters from the request const { service, programName, format, debug } = req.params; @@ -161,13 +191,6 @@ app.use("/:service/:programName/:format?/:debug?", (req, res, next) => { return; } - if(req.params.programName == "getAttr") { //Ben - ?? - req.params.programName = "RDM.GET.ATTR"; - } - - // Convert the program name to uppercase - req.params.programName = req.params.programName.toUpperCase(); - // Set the serviceConfig to the res.locals object try { res.locals.serviceConfig = require(path.join(__dirname, 'configs', service + '.json'));