From 463469381ddd95f620ef45318552d915df7723e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20Sander?= Date: Fri, 8 Mar 2024 13:54:49 +0000 Subject: [PATCH] fix(certificates): Handle --secure flag correctly, rejecting/allowing unauthorised certificates based on this flag. Fixes #416 --- .gitignore | 1 + src/__tests__/app_cert.test.js | 1 + src/__tests__/app_export_cert.test.js | 2 + src/__tests__/app_import_cert.test.js | 2 + src/__tests__/bookmark_get_cert.test.js | 2 + src/__tests__/bookmark_get_jwt.test.js | 2 + src/__tests__/connection_test_cert.test.js | 2 + src/__tests__/connection_test_jwt.test.js | 2 - src/__tests__/script_get_cert.test.js | 2 + src/__tests__/task_cert.test.js | 1 + .../task_custom_property_set_cert.test.js | 2 + .../task_custom_property_set_jwt.test.js | 2 + src/__tests__/task_get_cert.test.js | 2 + src/__tests__/task_import_cert.test.js | 2 + src/__tests__/task_jwt.test.js | 13 ++- src/ctrl-q.js | 100 ++++++++++++++---- src/lib/app/class_allapps.js | 15 +++ src/lib/task/class_allcompositeevents.js | 2 + src/lib/task/class_allschemaevents.js | 2 + src/lib/task/class_alltasks.js | 9 ++ src/lib/task/task_qrs.js | 4 + src/lib/util/about.js | 2 + src/lib/util/app.js | 8 ++ src/lib/util/cert.js | 5 +- src/lib/util/customproperties.js | 2 + src/lib/util/proxy.js | 2 + src/lib/util/qps.js | 5 +- src/lib/util/qrs.js | 5 +- src/lib/util/session.js | 6 ++ src/lib/util/tag.js | 2 + src/lib/util/task.js | 12 +++ 31 files changed, 191 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index 7c19fe7..46eb34e 100644 --- a/.gitignore +++ b/.gitignore @@ -137,3 +137,4 @@ tasktree.json tasktable.csv task-chain.csv .vscode/launch.json +.vscode/launch.json diff --git a/src/__tests__/app_cert.test.js b/src/__tests__/app_cert.test.js index 074ee37..88d1725 100644 --- a/src/__tests__/app_cert.test.js +++ b/src/__tests__/app_cert.test.js @@ -8,6 +8,7 @@ const options = { authType: process.env.CTRL_Q_AUTH_TYPE || 'cert', authCertFile: process.env.CTRL_Q_AUTH_CERT_FILE || './cert/client.pem', authCertKeyFile: process.env.CTRL_Q_AUTH_CERT_KEY_FILE || './cert/client_key.pem', + authRootCertFile: process.env.CTRL_Q_AUTH_ROOT_CERT_FILE || './cert/root.pem', host: process.env.CTRL_Q_HOST || '', port: process.env.CTRL_Q_PORT || '4242', schemaVersion: process.env.CTRL_Q_SCHEMA_VERSION || '12.612.0', diff --git a/src/__tests__/app_export_cert.test.js b/src/__tests__/app_export_cert.test.js index 3c0790d..17c3004 100644 --- a/src/__tests__/app_export_cert.test.js +++ b/src/__tests__/app_export_cert.test.js @@ -11,6 +11,7 @@ const options = { authType: process.env.CTRL_Q_AUTH_TYPE || 'cert', authCertFile: process.env.CTRL_Q_AUTH_CERT_FILE || './cert/client.pem', authCertKeyFile: process.env.CTRL_Q_AUTH_CERT_KEY_FILE || './cert/client_key.pem', + authRootCertFile: process.env.CTRL_Q_AUTH_ROOT_CERT_FILE || './cert/root.pem', host: process.env.CTRL_Q_HOST || '', port: process.env.CTRL_Q_PORT || '4242', schemaVersion: process.env.CTRL_Q_SCHEMA_VERSION || '12.612.0', @@ -31,6 +32,7 @@ describe('export apps to QVF files (cert auth)', () => { test('get tasks (verify parameters)', async () => { expect(options.authCertFile).not.toHaveLength(0); expect(options.authCertKeyFile).not.toHaveLength(0); + expect(options.authRootCertFile).not.toHaveLength(0); expect(options.host).not.toHaveLength(0); expect(options.authUserDir).not.toHaveLength(0); expect(options.authUserId).not.toHaveLength(0); diff --git a/src/__tests__/app_import_cert.test.js b/src/__tests__/app_import_cert.test.js index 5127971..d6ee4ab 100644 --- a/src/__tests__/app_import_cert.test.js +++ b/src/__tests__/app_import_cert.test.js @@ -9,6 +9,7 @@ const options = { authType: process.env.CTRL_Q_AUTH_TYPE || 'cert', authCertFile: process.env.CTRL_Q_AUTH_CERT_FILE || './cert/client.pem', authCertKeyFile: process.env.CTRL_Q_AUTH_CERT_KEY_FILE || './cert/client_key.pem', + authRootCertFile: process.env.CTRL_Q_AUTH_ROOT_CERT_FILE || './cert/root.pem', host: process.env.CTRL_Q_HOST || '', port: process.env.CTRL_Q_PORT || '4242', schemaVersion: process.env.CTRL_Q_SCHEMA_VERSION || '12.612.0', @@ -34,6 +35,7 @@ describe('import apps from QVF files (cert auth)', () => { test('get tasks (verify parameters)', async () => { expect(options.authCertFile).not.toHaveLength(0); expect(options.authCertKeyFile).not.toHaveLength(0); + expect(options.authRootCertFile).not.toHaveLength(0); expect(options.host).not.toHaveLength(0); expect(options.authUserDir).not.toHaveLength(0); expect(options.authUserId).not.toHaveLength(0); diff --git a/src/__tests__/bookmark_get_cert.test.js b/src/__tests__/bookmark_get_cert.test.js index 20cc517..6a9ec50 100644 --- a/src/__tests__/bookmark_get_cert.test.js +++ b/src/__tests__/bookmark_get_cert.test.js @@ -8,6 +8,7 @@ const options = { authType: process.env.CTRL_Q_AUTH_TYPE || 'cert', authCertFile: process.env.CTRL_Q_AUTH_CERT_FILE || './cert/client.pem', authCertKeyFile: process.env.CTRL_Q_AUTH_CERT_KEY_FILE || './cert/client_key.pem', + authRootCertFile: process.env.CTRL_Q_AUTH_ROOT_CERT_FILE || './cert/root.pem', host: process.env.CTRL_Q_HOST || '', port: process.env.CTRL_Q_PORT || '4747', schemaVersion: process.env.CTRL_Q_SCHEMA_VERSION || '12.612.0', @@ -32,6 +33,7 @@ const appIdExistsHasBookmarks1Bookmark2 = 'c49210ea-3005-4f2c-8697-52fe541b51d8' test('get bookmark (verify parameters)', async () => { expect(options.authCertFile).not.toHaveLength(0); expect(options.authCertKeyFile).not.toHaveLength(0); + expect(options.authRootCertFile).not.toHaveLength(0); expect(options.host).not.toHaveLength(0); expect(options.authUserDir).not.toHaveLength(0); expect(options.authUserId).not.toHaveLength(0); diff --git a/src/__tests__/bookmark_get_jwt.test.js b/src/__tests__/bookmark_get_jwt.test.js index 49f8eab..b6447eb 100644 --- a/src/__tests__/bookmark_get_jwt.test.js +++ b/src/__tests__/bookmark_get_jwt.test.js @@ -8,6 +8,7 @@ const options = { authType: process.env.CTRL_Q_AUTH_TYPE || 'cert', authCertFile: process.env.CTRL_Q_AUTH_CERT_FILE || './cert/client.pem', authCertKeyFile: process.env.CTRL_Q_AUTH_CERT_KEY_FILE || './cert/client_key.pem', + authRootCertFile: process.env.CTRL_Q_AUTH_ROOT_CERT_FILE || './cert/root.pem', host: process.env.CTRL_Q_HOST || '', port: process.env.CTRL_Q_PORT || '4747', schemaVersion: process.env.CTRL_Q_SCHEMA_VERSION || '12.612.0', @@ -37,6 +38,7 @@ options.virtualProxy = 'jwt'; test('get bookmark (verify parameters)', async () => { expect(options.authCertFile).not.toHaveLength(0); expect(options.authCertKeyFile).not.toHaveLength(0); + expect(options.authRootCertFile).not.toHaveLength(0); expect(options.host).not.toHaveLength(0); expect(options.authUserDir).not.toHaveLength(0); expect(options.authUserId).not.toHaveLength(0); diff --git a/src/__tests__/connection_test_cert.test.js b/src/__tests__/connection_test_cert.test.js index 1546c83..244c9ae 100644 --- a/src/__tests__/connection_test_cert.test.js +++ b/src/__tests__/connection_test_cert.test.js @@ -8,6 +8,7 @@ const options = { authType: process.env.CTRL_Q_AUTH_TYPE, authCertFile: process.env.CTRL_Q_AUTH_CERT_FILE || './cert/client.pem', authCertKeyFile: process.env.CTRL_Q_AUTH_CERT_KEY_FILE || './cert/client_key.pem', + authRootCertFile: process.env.CTRL_Q_AUTH_ROOT_CERT_FILE || './cert/root.pem', host: process.env.CTRL_Q_HOST || '', port: process.env.CTRL_Q_PORT || '', virtualProxy: process.env.CTRL_Q_VIRTUAL_PROXY || '', @@ -30,6 +31,7 @@ describe('connection test (cert auth)', () => { expect(options.authType).toBe('cert'); expect(options.authCertFile).not.toHaveLength(0); expect(options.authCertKeyFile).not.toHaveLength(0); + expect(options.authRootCertFile).not.toHaveLength(0); expect(options.host).not.toHaveLength(0); expect(options.authUserDir).not.toHaveLength(0); expect(options.authUserId).not.toHaveLength(0); diff --git a/src/__tests__/connection_test_jwt.test.js b/src/__tests__/connection_test_jwt.test.js index d5a672d..28002c6 100644 --- a/src/__tests__/connection_test_jwt.test.js +++ b/src/__tests__/connection_test_jwt.test.js @@ -6,8 +6,6 @@ import testConnection from '../lib/cmd/testconnection.js'; const options = { logLevel: process.env.CTRL_Q_LOG_LEVEL || 'info', authType: process.env.CTRL_Q_AUTH_TYPE, - authCertFile: process.env.CTRL_Q_AUTH_CERT_FILE || './cert/client.pem', - authCertKeyFile: process.env.CTRL_Q_AUTH_CERT_KEY_FILE || './cert/client_key.pem', host: process.env.CTRL_Q_HOST || '', port: process.env.CTRL_Q_PORT || '', virtualProxy: process.env.CTRL_Q_VIRTUAL_PROXY || '', diff --git a/src/__tests__/script_get_cert.test.js b/src/__tests__/script_get_cert.test.js index f608a37..11ea145 100644 --- a/src/__tests__/script_get_cert.test.js +++ b/src/__tests__/script_get_cert.test.js @@ -8,6 +8,7 @@ const options = { authType: process.env.CTRL_Q_AUTH_TYPE || 'cert', authCertFile: process.env.CTRL_Q_AUTH_CERT_FILE || './cert/client.pem', authCertKeyFile: process.env.CTRL_Q_AUTH_CERT_KEY_FILE || './cert/client_key.pem', + authRootCertFile: process.env.CTRL_Q_AUTH_ROOT_CERT_FILE || './cert/root.pem', host: process.env.CTRL_Q_HOST || '', port: process.env.CTRL_Q_PORT || '4747', virtualProxy: process.env.CTRL_Q_VIRTUAL_PROXY || '', @@ -27,6 +28,7 @@ describe('get app script (cert auth)', () => { test('Verify parameters', async () => { expect(options.authCertFile).not.toHaveLength(0); expect(options.authCertKeyFile).not.toHaveLength(0); + expect(options.authRootCertFile).not.toHaveLength(0); expect(options.host).not.toHaveLength(0); expect(options.authUserDir).not.toHaveLength(0); expect(options.authUserId).not.toHaveLength(0); diff --git a/src/__tests__/task_cert.test.js b/src/__tests__/task_cert.test.js index c6756c9..39cde42 100644 --- a/src/__tests__/task_cert.test.js +++ b/src/__tests__/task_cert.test.js @@ -8,6 +8,7 @@ const options = { authType: process.env.CTRL_Q_AUTH_TYPE || 'cert', authCertFile: process.env.CTRL_Q_AUTH_CERT_FILE || './cert/client.pem', authCertKeyFile: process.env.CTRL_Q_AUTH_CERT_KEY_FILE || './cert/client_key.pem', + authRootCertFile: process.env.CTRL_Q_AUTH_ROOT_CERT_FILE || './cert/root.pem', host: process.env.CTRL_Q_HOST || '', port: process.env.CTRL_Q_PORT || '4242', schemaVersion: process.env.CTRL_Q_SCHEMA_VERSION || '12.612.0', diff --git a/src/__tests__/task_custom_property_set_cert.test.js b/src/__tests__/task_custom_property_set_cert.test.js index 6b2892c..bc38bfb 100644 --- a/src/__tests__/task_custom_property_set_cert.test.js +++ b/src/__tests__/task_custom_property_set_cert.test.js @@ -9,6 +9,7 @@ const options = { authType: process.env.CTRL_Q_AUTH_TYPE || 'cert', authCertFile: process.env.CTRL_Q_AUTH_CERT_FILE || './cert/client.pem', authCertKeyFile: process.env.CTRL_Q_AUTH_CERT_KEY_FILE || './cert/client_key.pem', + authRootCertFile: process.env.CTRL_Q_AUTH_ROOT_CERT_FILE || './cert/root.pem', host: process.env.CTRL_Q_HOST || '', port: process.env.CTRL_Q_PORT || '4242', schemaVersion: process.env.CTRL_Q_SCHEMA_VERSION || '12.612.0', @@ -34,6 +35,7 @@ const existingTaskId = 'e9100e69-4e8e-414b-bf88-10a1110c43a9'; test('set custom properties (verify parameters)', async () => { expect(options.authCertFile).not.toHaveLength(0); expect(options.authCertKeyFile).not.toHaveLength(0); + expect(options.authRootCertFile).not.toHaveLength(0); expect(options.host).not.toHaveLength(0); expect(options.authUserDir).not.toHaveLength(0); expect(options.authUserId).not.toHaveLength(0); diff --git a/src/__tests__/task_custom_property_set_jwt.test.js b/src/__tests__/task_custom_property_set_jwt.test.js index c69bf98..3ce06af 100644 --- a/src/__tests__/task_custom_property_set_jwt.test.js +++ b/src/__tests__/task_custom_property_set_jwt.test.js @@ -9,6 +9,7 @@ const options = { authType: process.env.CTRL_Q_AUTH_TYPE || 'jwt', authCertFile: process.env.CTRL_Q_AUTH_CERT_FILE || './cert/client.pem', authCertKeyFile: process.env.CTRL_Q_AUTH_CERT_KEY_FILE || './cert/client_key.pem', + authRootCertFile: process.env.CTRL_Q_AUTH_ROOT_CERT_FILE || './cert/root.pem', host: process.env.CTRL_Q_HOST || '', port: process.env.CTRL_Q_PORT || '443', schemaVersion: process.env.CTRL_Q_SCHEMA_VERSION || '12.612.0', @@ -30,6 +31,7 @@ const existingTaskId = 'e9100e69-4e8e-414b-bf88-10a1110c43a9'; test('set custom properties (verify parameters)', async () => { expect(options.authCertFile).not.toHaveLength(0); expect(options.authCertKeyFile).not.toHaveLength(0); + expect(options.authRootCertFile).not.toHaveLength(0); expect(options.host).not.toHaveLength(0); expect(options.authUserDir).not.toHaveLength(0); expect(options.authUserId).not.toHaveLength(0); diff --git a/src/__tests__/task_get_cert.test.js b/src/__tests__/task_get_cert.test.js index 0a9bf33..bc128a2 100644 --- a/src/__tests__/task_get_cert.test.js +++ b/src/__tests__/task_get_cert.test.js @@ -10,6 +10,7 @@ const options = { authType: process.env.CTRL_Q_AUTH_TYPE || 'cert', authCertFile: process.env.CTRL_Q_AUTH_CERT_FILE || './cert/client.pem', authCertKeyFile: process.env.CTRL_Q_AUTH_CERT_KEY_FILE || './cert/client_key.pem', + authRootCertFile: process.env.CTRL_Q_AUTH_ROOT_CERT_FILE || './cert/root.pem', host: process.env.CTRL_Q_HOST || '', port: process.env.CTRL_Q_PORT || '4242', schemaVersion: process.env.CTRL_Q_SCHEMA_VERSION || '12.612.0', @@ -28,6 +29,7 @@ jest.setTimeout(defaultTestTimeout); test('get tasks (verify parameters) ', async () => { expect(options.authCertFile).not.toHaveLength(0); expect(options.authCertKeyFile).not.toHaveLength(0); + expect(options.authRootCertFile).not.toHaveLength(0); expect(options.host).not.toHaveLength(0); expect(options.authUserDir).not.toHaveLength(0); expect(options.authUserId).not.toHaveLength(0); diff --git a/src/__tests__/task_import_cert.test.js b/src/__tests__/task_import_cert.test.js index dfbfc49..b2666e4 100644 --- a/src/__tests__/task_import_cert.test.js +++ b/src/__tests__/task_import_cert.test.js @@ -11,6 +11,7 @@ const options = { authType: process.env.CTRL_Q_AUTH_TYPE || 'cert', authCertFile: process.env.CTRL_Q_AUTH_CERT_FILE || './cert/client.pem', authCertKeyFile: process.env.CTRL_Q_AUTH_CERT_KEY_FILE || './cert/client_key.pem', + authRootCertFile: process.env.CTRL_Q_AUTH_ROOT_CERT_FILE || './cert/root.pem', host: process.env.CTRL_Q_HOST || '', port: process.env.CTRL_Q_PORT || '4242', schemaVersion: process.env.CTRL_Q_SCHEMA_VERSION || '12.612.0', @@ -29,6 +30,7 @@ describe('import task (cert auth)', () => { test('get tasks (verify parameters)', async () => { expect(options.authCertFile).not.toHaveLength(0); expect(options.authCertKeyFile).not.toHaveLength(0); + expect(options.authRootCertFile).not.toHaveLength(0); expect(options.host).not.toHaveLength(0); expect(options.authUserDir).not.toHaveLength(0); expect(options.authUserId).not.toHaveLength(0); diff --git a/src/__tests__/task_jwt.test.js b/src/__tests__/task_jwt.test.js index 986b387..6ebbf33 100644 --- a/src/__tests__/task_jwt.test.js +++ b/src/__tests__/task_jwt.test.js @@ -6,8 +6,6 @@ import { taskExistById, getTaskByName, getTaskById } from '../lib/util/task.js'; const options = { logLevel: process.env.CTRL_Q_LOG_LEVEL || 'info', authType: process.env.CTRL_Q_AUTH_TYPE || 'cert', - authCertFile: process.env.CTRL_Q_AUTH_CERT_FILE || './cert/client.pem', - authCertKeyFile: process.env.CTRL_Q_AUTH_CERT_KEY_FILE || './cert/client_key.pem', host: process.env.CTRL_Q_HOST || '', port: process.env.CTRL_Q_PORT || '4242', schemaVersion: process.env.CTRL_Q_SCHEMA_VERSION || '12.612.0', @@ -15,6 +13,7 @@ const options = { secure: process.env.CTRL_Q_SECURE || true, authUserDir: process.env.CTRL_Q_AUTH_USER_DIR || '', authUserId: process.env.CTRL_Q_AUTH_USER_ID || '', + authJwt: process.env.CTRL_Q_AUTH_JWT || '', taskType: process.env.CTRL_Q_TASK_TYPE || 'reload', }; @@ -36,8 +35,12 @@ const multipleMatchingTaskNames = '[ctrl-q unit test] app 1, task 2 (duplicates const nonExistingTaskId = '9f0d0e02-cccc-bbbb-aaaa-3e9a4d0c8a3d'; const nonExistingTaskName = 'Non-existing task 298374293874298734'; +options.authType = 'jwt'; +options.port = '443'; +options.virtualProxy = 'jwt'; + // Check if task exists by ID -describe('taskExistById: Check if task exists by ID (cert auth)', () => { +describe('taskExistById: Check if task exists by ID (jwt auth)', () => { test('existing task', async () => { const result = await taskExistById(existingTaskId, options); expect(result).toBe(true); @@ -50,7 +53,7 @@ describe('taskExistById: Check if task exists by ID (cert auth)', () => { }); // Get task by name -describe('getTaskByName: Get task by name (cert auth)', () => { +describe('getTaskByName: Get task by name (jwt auth)', () => { test('no matching task', async () => { const result = await getTaskByName(nonExistingTaskName, options); expect(result).toBe(false); @@ -80,7 +83,7 @@ describe('getTaskByName: Get task by name (cert auth)', () => { }); // Get task by ID -describe('getTaskById: Get task by ID (cert auth)', () => { +describe('getTaskById: Get task by ID (jwt auth)', () => { test('no matching task', async () => { const result = await getTaskById(nonExistingTaskId, options); expect(result).toEqual(false); diff --git a/src/ctrl-q.js b/src/ctrl-q.js index 20ccdc2..058dd9d 100644 --- a/src/ctrl-q.js +++ b/src/ctrl-q.js @@ -95,7 +95,7 @@ const program = new Command(); // .requiredOption('--host ', 'Qlik Sense server IP/FQDN') // .option('--port ', 'Qlik Sense repository API port', '4242') // .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - // .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + // .requiredOption('--secure ', 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', true) // .option('--auth-user-dir ', 'user directory for user to connect with', 'Internal') // .option('--auth-user-id ', 'user ID for user to connect with', 'sa_repository') @@ -143,7 +143,11 @@ const program = new Command(); .option('--schema-version ', 'Qlik Sense engine schema version', '12.612.0') .requiredOption('--app-id ', 'Qlik Sense app ID') .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + .requiredOption( + '--secure ', + 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', + true + ) .requiredOption('--auth-user-dir ', 'user directory for user to connect with') .requiredOption('--auth-user-id ', 'user ID for user to connect with') @@ -231,7 +235,11 @@ const program = new Command(); .option('--schema-version ', 'Qlik Sense engine schema version', '12.612.0') .requiredOption('--app-id ', 'Qlik Sense app ID') .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + .requiredOption( + '--secure ', + 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', + true + ) .requiredOption('--auth-user-dir ', 'user directory for user to connect with') .requiredOption('--auth-user-id ', 'user ID for user to connect with') @@ -265,7 +273,11 @@ const program = new Command(); .option('--schema-version ', 'Qlik Sense engine schema version', '12.612.0') .requiredOption('--app-id ', 'Qlik Sense app ID') .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + .requiredOption( + '--secure ', + 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', + true + ) .requiredOption('--auth-user-dir ', 'user directory for user to connect with') .requiredOption('--auth-user-id ', 'user ID for user to connect with') @@ -297,7 +309,11 @@ const program = new Command(); .option('--schema-version ', 'Qlik Sense engine schema version', '12.612.0') .requiredOption('--app-id ', 'Qlik Sense app ID') .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + .requiredOption( + '--secure ', + 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', + true + ) .requiredOption('--auth-user-dir ', 'user directory for user to connect with') .requiredOption('--auth-user-id ', 'user ID for user to connect with') @@ -331,7 +347,11 @@ const program = new Command(); .option('--schema-version ', 'Qlik Sense engine schema version', '12.612.0') .requiredOption('--app-id ', 'Qlik Sense app ID') .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + .requiredOption( + '--secure ', + 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', + true + ) .requiredOption('--auth-user-dir ', 'user directory for user to connect with') .requiredOption('--auth-user-id ', 'user ID for user to connect with') @@ -366,7 +386,11 @@ const program = new Command(); .option('--app-id ', 'Qlik Sense app ID(s) to get variables from') .option('--app-tag ', 'Qlik Sense app tag(s) to get variables') .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + .requiredOption( + '--secure ', + 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', + true + ) .requiredOption('--auth-user-dir ', 'user directory for user to connect with') .requiredOption('--auth-user-id ', 'user ID for user to connect with') @@ -402,7 +426,11 @@ const program = new Command(); .option('--app-id ', 'Qlik Sense app ID(s) to get variables from') .option('--app-tag ', 'Qlik Sense app tag(s) to get variables') .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + .requiredOption( + '--secure ', + 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', + true + ) .requiredOption('--auth-user-dir ', 'user directory for user to connect with') .requiredOption('--auth-user-id ', 'user ID for user to connect with') @@ -436,7 +464,11 @@ const program = new Command(); .option('--schema-version ', 'Qlik Sense engine schema version', '12.612.0') .requiredOption('--app-id ', 'Qlik Sense app ID') .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + .requiredOption( + '--secure ', + 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', + true + ) .requiredOption('--auth-user-dir ', 'user directory for user to connect with') .requiredOption('--auth-user-id ', 'user ID for user to connect with') @@ -467,7 +499,11 @@ const program = new Command(); .option('--schema-version ', 'Qlik Sense engine schema version', '12.612.0') .requiredOption('--app-id ', 'Qlik Sense app ID') .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + .requiredOption( + '--secure ', + 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', + true + ) .requiredOption('--auth-user-dir ', 'user directory for user to connect with') .requiredOption('--auth-user-id ', 'user ID for user to connect with') @@ -495,7 +531,11 @@ const program = new Command(); .option('--schema-version ', 'Qlik Sense engine schema version', '12.612.0') .requiredOption('--app-id ', 'Qlik Sense app ID') .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + .requiredOption( + '--secure ', + 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', + true + ) .requiredOption('--auth-user-dir ', 'user directory for user to connect with') .requiredOption('--auth-user-id ', 'user ID for user to connect with') @@ -543,7 +583,11 @@ const program = new Command(); .option('--port ', 'Qlik Sense repository service (QRS) port (usually 4242 for cert auth, 443 for jwt auth)', '4242') .option('--schema-version ', 'Qlik Sense engine schema version', '12.612.0') .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + .requiredOption( + '--secure ', + 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', + true + ) .requiredOption('--auth-user-dir ', 'user directory for user to connect with') .requiredOption('--auth-user-id ', 'user ID for user to connect with') @@ -598,7 +642,11 @@ const program = new Command(); .option('--port ', 'Qlik Sense repository service (QRS) port (usually 4242 for cert auth, 443 for jwt auth)', '4242') .option('--schema-version ', 'Qlik Sense engine schema version', '12.612.0') .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + .requiredOption( + '--secure ', + 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', + true + ) .requiredOption('--auth-user-dir ', 'user directory for user to connect with') .requiredOption('--auth-user-id ', 'user ID for user to connect with') @@ -646,7 +694,11 @@ const program = new Command(); .option('--port ', 'Qlik Sense repository service (QRS) port (usually 4242 for cert auth, 443 for jwt auth)', '4242') .option('--schema-version ', 'Qlik Sense engine schema version', '12.612.0') .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + .requiredOption( + '--secure ', + 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', + true + ) .requiredOption('--auth-user-dir ', 'user directory for user to connect with') .requiredOption('--auth-user-id ', 'user ID for user to connect with') @@ -698,7 +750,11 @@ const program = new Command(); .option('--port ', 'Qlik Sense repository service (QRS) port (usually 4242 for cert auth, 443 for jwt auth)', '4242') .option('--schema-version ', 'Qlik Sense engine schema version', '12.612.0') .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + .requiredOption( + '--secure ', + 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', + true + ) .requiredOption('--auth-user-dir ', 'user directory for user to connect with') .requiredOption('--auth-user-id ', 'user ID for user to connect with') @@ -741,7 +797,11 @@ const program = new Command(); .option('--port ', 'Qlik Sense repository service (QRS) port (usually 4242 for cert auth, 443 for jwt auth)', '4242') .option('--schema-version ', 'Qlik Sense engine schema version', '12.612.0') .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + .requiredOption( + '--secure ', + 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', + true + ) .requiredOption('--auth-user-dir ', 'user directory for user to connect with') .requiredOption('--auth-user-id ', 'user ID for user to connect with') @@ -802,7 +862,11 @@ const program = new Command(); .option('--port ', 'Qlik Sense proxy service port', '4242') .option('--schema-version ', 'Qlik Sense engine schema version', '12.612.0') .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + .requiredOption( + '--secure ', + 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', + true + ) .requiredOption('--auth-user-dir ', 'user directory for user to connect with') .requiredOption('--auth-user-id ', 'user ID for user to connect with') @@ -840,7 +904,7 @@ const program = new Command(); .option('--port ', 'Qlik Sense repository service (QRS) port (usually 4242 for cert auth, 443 for jwt auth)', '4242') // .option('--schema-version ', 'Qlik Sense engine schema version', '12.612.0') .requiredOption('--virtual-proxy ', 'Qlik Sense virtual proxy prefix', '') - // .requiredOption('--secure ', 'connection to Qlik Sense engine is via https', true) + // .requiredOption('--secure ', 'https connection to Qlik Sense must use correct certificate. Invalid certificates will result in rejected/failed connection.', true) .requiredOption('--auth-user-dir ', 'user directory for user to connect with') .requiredOption('--auth-user-id ', 'user ID for user to connect with') diff --git a/src/lib/app/class_allapps.js b/src/lib/app/class_allapps.js index 541d960..5325173 100644 --- a/src/lib/app/class_allapps.js +++ b/src/lib/app/class_allapps.js @@ -31,6 +31,7 @@ class QlikSenseApps { // Make sure certificates exist this.fileCert = path.resolve(execPath, options.authCertFile); this.fileCertKey = path.resolve(execPath, options.authCertKeyFile); + this.fileCertCA = path.resolve(execPath, options.authRootCertFile); } // Map that will connect app counter from Excel file with ID an app gets after import to QSEoW @@ -113,6 +114,7 @@ class QlikSenseApps { method: 'get', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: '/qrs/app/full', }); } else { @@ -120,6 +122,7 @@ class QlikSenseApps { method: 'get', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: '/qrs/app/full', queryParameters: [{ name: 'filter', value: filter }], }); @@ -555,6 +558,7 @@ class QlikSenseApps { method: 'get', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: `/qrs/app/${uploadedAppId}`, }); } else if (this.options.authType === 'jwt') { @@ -596,6 +600,7 @@ class QlikSenseApps { method: 'get', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: '/qrs/user', queryParameters: [{ name: 'filter', value: filter }], }); @@ -644,6 +649,7 @@ class QlikSenseApps { method: 'put', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: `/qrs/app/${app.id}`, body: app, }); @@ -865,6 +871,7 @@ class QlikSenseApps { method: 'put', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: `/qrs/app/${appId}/publish`, queryParameters, }); @@ -910,6 +917,7 @@ class QlikSenseApps { method: 'put', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: `/qrs/app/${sourceAppId}/replace`, queryParameters, }); @@ -970,6 +978,7 @@ class QlikSenseApps { method: 'get', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: `/qrs/app`, queryParameters: [{ name: 'filter', value: filter }], }); @@ -1016,6 +1025,7 @@ class QlikSenseApps { method: 'get', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: `/qrs/app`, queryParameters: [{ name: 'filter', value: filter }], }); @@ -1078,6 +1088,7 @@ class QlikSenseApps { method: 'get', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: `/qrs/stream/${uploadedAppInfo.appPublishToStream}`, }); } else if (this.options.authType === 'jwt') { @@ -1106,6 +1117,7 @@ class QlikSenseApps { method: 'get', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: '/qrs/stream', queryParameters: [{ name: 'filter', value: filter }], }); @@ -1172,6 +1184,7 @@ class QlikSenseApps { method: 'post', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: '/qrs/app/upload', body: form, headers: { @@ -1266,6 +1279,7 @@ class QlikSenseApps { method: 'post', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: `/qrs/app/${app.id}/export/${exportToken}`, queryParameters: [{ name: 'skipData', value: excludeData }], }); @@ -1378,6 +1392,7 @@ class QlikSenseApps { method: 'get', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: urlPath, queryParameters: [{ name: paramName, value: paramValue }], }); diff --git a/src/lib/task/class_allcompositeevents.js b/src/lib/task/class_allcompositeevents.js index f487176..f6dab0e 100644 --- a/src/lib/task/class_allcompositeevents.js +++ b/src/lib/task/class_allcompositeevents.js @@ -20,6 +20,7 @@ class QlikSenseCompositeEvents { // Make sure certificates exist this.fileCert = path.resolve(execPath, options.authCertFile); this.fileCertKey = path.resolve(execPath, options.authCertKeyFile); + this.fileCertCA = path.resolve(execPath, options.authRootCertFile); } } catch (err) { catchLog(`GET COMPOSITE EVENT`, err); @@ -45,6 +46,7 @@ class QlikSenseCompositeEvents { method: 'get', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: '/qrs/compositeevent/full', }); diff --git a/src/lib/task/class_allschemaevents.js b/src/lib/task/class_allschemaevents.js index c5556ce..b0a9866 100644 --- a/src/lib/task/class_allschemaevents.js +++ b/src/lib/task/class_allschemaevents.js @@ -20,6 +20,7 @@ class QlikSenseSchemaEvents { // Make sure certificates exist this.fileCert = path.resolve(execPath, options.authCertFile); this.fileCertKey = path.resolve(execPath, options.authCertKeyFile); + this.fileCertCA = path.resolve(execPath, options.authRootCertFile); } } catch (err) { catchLog(`GET SCHEMA EVENT INIT`, err); @@ -62,6 +63,7 @@ class QlikSenseSchemaEvents { method: 'get', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: '/qrs/schemaevent/full', }); diff --git a/src/lib/task/class_alltasks.js b/src/lib/task/class_alltasks.js index 49c4d62..3663c3c 100644 --- a/src/lib/task/class_alltasks.js +++ b/src/lib/task/class_alltasks.js @@ -46,6 +46,7 @@ class QlikSenseTasks { // Make sure certificates exist this.fileCert = path.resolve(execPath, options.authCertFile); this.fileCertKey = path.resolve(execPath, options.authCertKeyFile); + this.fileCertCA = path.resolve(execPath, options.authRootCertFile); } this.qlikSenseSchemaEvents = new QlikSenseSchemaEvents(); @@ -1300,6 +1301,7 @@ class QlikSenseTasks { method: 'post', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: '/qrs/compositeevent', body, }); @@ -1369,6 +1371,7 @@ class QlikSenseTasks { method: 'post', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: '/qrs/reloadtask/create', body, }); @@ -1431,6 +1434,7 @@ class QlikSenseTasks { method: 'post', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: '/qrs/externalprogramtask/create', body, }); @@ -1497,6 +1501,7 @@ class QlikSenseTasks { method: 'post', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: '/qrs/reloadtask/create', body, }); @@ -1601,6 +1606,7 @@ class QlikSenseTasks { method: 'get', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: '/qrs/reloadtask/full', }); } else { @@ -1608,6 +1614,7 @@ class QlikSenseTasks { method: 'get', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: '/qrs/reloadtask/full', queryParameters: [{ name: 'filter', value: filter }], }); @@ -1625,6 +1632,7 @@ class QlikSenseTasks { method: 'get', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: '/qrs/externalprogramtask/full', }); } else { @@ -1632,6 +1640,7 @@ class QlikSenseTasks { method: 'get', fileCert: this.fileCert, fileCertKey: this.fileCertKey, + fileCertCA: this.fileCertCA, path: '/qrs/externalprogramtask/full', queryParameters: [{ name: 'filter', value: filter }], }); diff --git a/src/lib/task/task_qrs.js b/src/lib/task/task_qrs.js index b339aee..22209c3 100644 --- a/src/lib/task/task_qrs.js +++ b/src/lib/task/task_qrs.js @@ -35,6 +35,7 @@ export const getCustomProperty = async (options) => { method: 'get', fileCert: certFilesFullPath.fileCert, fileCertKey: certFilesFullPath.fileCertKey, + fileCertCA: certFilesFullPath.fileCertCA, path: '/qrs/CustomPropertyDefinition/full', queryParameters: [{ name: 'filter', value: filter }], }); @@ -68,6 +69,7 @@ export const getTasksFromQseow = async (options) => { // Get QRS certificates const fileCert = path.resolve(execPath, options.authCertFile); const fileCertKey = path.resolve(execPath, options.authCertKeyFile); + const fileCertCA = path.resolve(execPath, options.authRootCertFile); // // Build QRS query string using task IDs @@ -112,6 +114,7 @@ export const getTasksFromQseow = async (options) => { method: 'get', fileCert, fileCertKey, + fileCertCA, path: '/qrs/reloadtask/full', queryParameters: [{ name: 'filter', value: filter }], }); @@ -143,6 +146,7 @@ export const updateReloadTask = async (options, payload) => { method: 'post', fileCert: certFilesFullPath.fileCert, fileCertKey: certFilesFullPath.fileCertKey, + fileCertCA: certFilesFullPath.fileCertCA, path: '/qrs/reloadtask/update', body: payload, }); diff --git a/src/lib/util/about.js b/src/lib/util/about.js index 9833d89..d0803f7 100644 --- a/src/lib/util/about.js +++ b/src/lib/util/about.js @@ -14,11 +14,13 @@ function getAboutFromQseow(options) { // Make sure certificates exist const fileCert = path.resolve(execPath, options.authCertFile); const fileCertKey = path.resolve(execPath, options.authCertKeyFile); + const fileCertCA = path.resolve(execPath, options.authRootCertFile); axiosConfig = setupQRSConnection(options, { method: 'get', fileCert, fileCertKey, + fileCertCA, path: '/qrs/about', }); } else if (options.authType === 'jwt') { diff --git a/src/lib/util/app.js b/src/lib/util/app.js index fc8631f..bab6816 100644 --- a/src/lib/util/app.js +++ b/src/lib/util/app.js @@ -68,11 +68,13 @@ export async function getApps(options, idArray, tagArray) { // Make sure certificates exist const fileCert = path.resolve(execPath, options.authCertFile); const fileCertKey = path.resolve(execPath, options.authCertKeyFile); + const fileCertCA = path.resolve(execPath, options.authRootCertFile); axiosConfig = setupQRSConnection(options, { method: 'get', fileCert, fileCertKey, + fileCertCA, path: '/qrs/app/full', queryParameters: [{ name: 'filter', value: filter }], }); @@ -123,11 +125,13 @@ export async function getAppById(appId, optionsParam) { // Make sure certificates exist const fileCert = path.resolve(execPath, options.authCertFile); const fileCertKey = path.resolve(execPath, options.authCertKeyFile); + const fileCertCA = path.resolve(execPath, options.authRootCertFile); axiosConfig = setupQRSConnection(options, { method: 'get', fileCert, fileCertKey, + fileCertCA, path: `/qrs/app/${appId}`, }); } else if (options.authType === 'jwt') { @@ -180,11 +184,13 @@ export async function deleteAppById(appId, options) { // Make sure certificates exist const fileCert = path.resolve(execPath, options.authCertFile); const fileCertKey = path.resolve(execPath, options.authCertKeyFile); + const fileCertCA = path.resolve(execPath, options.authRootCertFile); axiosConfig = setupQRSConnection(options, { method: 'delete', fileCert, fileCertKey, + fileCertCA, path: `/qrs/app/${appId}`, }); } else if (options.authType === 'jwt') { @@ -227,11 +233,13 @@ export async function appExistById(appId, options) { // Make sure certificates exist const fileCert = path.resolve(execPath, options.authCertFile); const fileCertKey = path.resolve(execPath, options.authCertKeyFile); + const fileCertCA = path.resolve(execPath, options.authRootCertFile); axiosConfig = setupQRSConnection(options, { method: 'get', fileCert, fileCertKey, + fileCertCA, path: '/qrs/app', queryParameters: [{ name: 'filter', value: encodeURI(`id eq ${appId}`) }], }); diff --git a/src/lib/util/cert.js b/src/lib/util/cert.js index b084deb..4bcd021 100644 --- a/src/lib/util/cert.js +++ b/src/lib/util/cert.js @@ -5,15 +5,18 @@ import { catchLog } from './log.js'; const getCertFilePaths = async (options) => { let fileCert; let fileCertKey; + let fileCertCA; + try { // Make sure QRS certificates exist fileCert = path.resolve(execPath, options.authCertFile); fileCertKey = path.resolve(execPath, options.authCertKeyFile); + fileCertCA = path.resolve(execPath, options.authRootCertFile); } catch (err) { catchLog('GET TASK QRS (ID). Exiting. ', err); process.exit(1); } - return { fileCert, fileCertKey }; + return { fileCert, fileCertKey, fileCertCA }; }; export default getCertFilePaths; diff --git a/src/lib/util/customproperties.js b/src/lib/util/customproperties.js index cafce4b..33a2d03 100644 --- a/src/lib/util/customproperties.js +++ b/src/lib/util/customproperties.js @@ -13,11 +13,13 @@ export function getCustomPropertiesFromQseow(options) { // Make sure certificates exist const fileCert = path.resolve(execPath, options.authCertFile); const fileCertKey = path.resolve(execPath, options.authCertKeyFile); + const fileCertCA = path.resolve(execPath, options.authRootCertFile); axiosConfig = setupQRSConnection(options, { method: 'get', fileCert, fileCertKey, + fileCertCA, path: '/qrs/custompropertydefinition/full', }); } else if (options.authType === 'jwt') { diff --git a/src/lib/util/proxy.js b/src/lib/util/proxy.js index 289fc68..7d51e7f 100644 --- a/src/lib/util/proxy.js +++ b/src/lib/util/proxy.js @@ -10,11 +10,13 @@ const getProxiesFromQseow = async (options, _sessionCookie) => { // Make sure certificates exist const fileCert = path.resolve(execPath, options.authCertFile); const fileCertKey = path.resolve(execPath, options.authCertKeyFile); + const fileCertCA = path.resolve(execPath, options.authRootCertFile); const axiosConfig = setupQRSConnection(options, { method: 'get', fileCert, fileCertKey, + fileCertCA, path: '/qrs/proxyservice/full', sessionCookie: null, }); diff --git a/src/lib/util/qps.js b/src/lib/util/qps.js index 0ab3561..ee9dd7b 100644 --- a/src/lib/util/qps.js +++ b/src/lib/util/qps.js @@ -20,11 +20,14 @@ const setupQPSConnection = (options, param) => { // Use cerrificates be used for authentication if (options.authType === 'cert') { logger.debug(`Using certificates for authentication with QPS`); + logger.debug(`QPS host: ${options.hostProxy}`); + logger.debug(`Reject unauthorized certificate: ${!!options.secure}`); const httpsAgent = new https.Agent({ - rejectUnauthorized: false, + rejectUnauthorized: options.secure !== 'false', cert: readCert(param.fileCert), key: readCert(param.fileCertKey), + ca: readCert(param.fileCertCA), }); axiosConfig = { diff --git a/src/lib/util/qrs.js b/src/lib/util/qrs.js index 5839e68..430d04f 100644 --- a/src/lib/util/qrs.js +++ b/src/lib/util/qrs.js @@ -44,11 +44,14 @@ const setupQRSConnection = (options, param) => { // Should cerrificates be used for authentication? if (options.authType === 'cert') { logger.debug(`Using certificates for authentication with QRS`); + logger.debug(`QRS host: ${options.host}`); + logger.debug(`Reject unauthorized certificate: ${options.secure}`); const httpsAgent = new https.Agent({ - rejectUnauthorized: false, + rejectUnauthorized: options.secure !== 'false', cert: readCert(param.fileCert), key: readCert(param.fileCertKey), + ca: readCert(param.fileCertCA), }); axiosConfig = { diff --git a/src/lib/util/session.js b/src/lib/util/session.js index 9dae02c..556140d 100644 --- a/src/lib/util/session.js +++ b/src/lib/util/session.js @@ -75,6 +75,7 @@ export const getSessionsFromQseow = async (options, sessionCookie) => { // Make sure certificates exist const fileCert = path.resolve(execPath, options.authCertFile); const fileCertKey = path.resolve(execPath, options.authCertKeyFile); + const fileCertCA = path.resolve(execPath, options.authRootCertFile); let axiosConfig; let virtualProxiesToProcess = []; @@ -92,6 +93,7 @@ export const getSessionsFromQseow = async (options, sessionCookie) => { method: 'get', fileCert, fileCertKey, + fileCertCA, path: '/qrs/virtualproxyconfig/full', queryParameters: [{ name: 'filter', value: encodeURI(vpFilter) }], }); @@ -101,6 +103,7 @@ export const getSessionsFromQseow = async (options, sessionCookie) => { method: 'get', fileCert, fileCertKey, + fileCertCA, path: '/qrs/virtualproxyconfig/full', }); } @@ -223,6 +226,7 @@ export const getSessionsFromQseow = async (options, sessionCookie) => { method: 'get', fileCert, fileCertKey, + fileCertCA, path: `/qps/${vp.prefix}/session`, sessionCookie: null, }); @@ -274,6 +278,7 @@ export const deleteSessionsFromQSEoWIds = async (options) => { // Make sure certificates exist const fileCert = path.resolve(execPath, options.authCertFile); const fileCertKey = path.resolve(execPath, options.authCertKeyFile); + const fileCertCA = path.resolve(execPath, options.authRootCertFile); try { const sessionDelete = []; @@ -359,6 +364,7 @@ export const deleteSessionsFromQSEoWIds = async (options) => { method: 'delete', fileCert, fileCertKey, + fileCertCA, path: `/qps/${options.sessionVirtualProxy}/session/${s.sessionId}`, sessionCookie: null, }); diff --git a/src/lib/util/tag.js b/src/lib/util/tag.js index 3ff7edd..bde341d 100644 --- a/src/lib/util/tag.js +++ b/src/lib/util/tag.js @@ -14,11 +14,13 @@ export function getTagsFromQseow(options) { // Make sure certificates exist const fileCert = path.resolve(execPath, options.authCertFile); const fileCertKey = path.resolve(execPath, options.authCertKeyFile); + const fileCertCA = path.resolve(execPath, options.authRootCertFile); axiosConfig = setupQRSConnection(options, { method: 'get', fileCert, fileCertKey, + fileCertCA, path: '/qrs/tag/full', }); } else if (options.authType === 'jwt') { diff --git a/src/lib/util/task.js b/src/lib/util/task.js index 9b31d1b..f88ef9f 100644 --- a/src/lib/util/task.js +++ b/src/lib/util/task.js @@ -21,6 +21,8 @@ export async function taskExistById(taskId, optionsParam) { options = optionsParam; } + logger.debug(`Auth type: ${options.authType}`); + // Is the task ID a valid GUID? if (!validate(taskId)) { logger.error(`TASK EXIST BY ID: Task ID ${taskId} is not a valid GUID.`); @@ -34,12 +36,14 @@ export async function taskExistById(taskId, optionsParam) { // Make sure certificates exist const fileCert = path.resolve(execPath, options.authCertFile); const fileCertKey = path.resolve(execPath, options.authCertKeyFile); + const fileCertCA = path.resolve(execPath, options.authRootCertFile); // const filter = encodeURI(`name eq '👍😎 updateSheetThumbnail'`); axiosConfig = setupQRSConnection(options, { method: 'get', fileCert, fileCertKey, + fileCertCA, path: '/qrs/task', queryParameters: [{ name: 'filter', value: encodeURI(`id eq ${taskId}`) }], }); @@ -102,11 +106,13 @@ export async function getTaskByName(taskName, optionsParam) { // Make sure certificates exist const fileCert = path.resolve(execPath, options.authCertFile); const fileCertKey = path.resolve(execPath, options.authCertKeyFile); + const fileCertCA = path.resolve(execPath, options.authRootCertFile); axiosConfig = setupQRSConnection(options, { method: 'get', fileCert, fileCertKey, + fileCertCA, path: '/qrs/task/full', queryParameters: [{ name: 'filter', value: encodeURI(`name eq '${taskName}'`) }], }); @@ -172,11 +178,13 @@ export async function getTaskById(taskId, optionsParam) { // Make sure certificates exist const fileCert = path.resolve(execPath, options.authCertFile); const fileCertKey = path.resolve(execPath, options.authCertKeyFile); + const fileCertCA = path.resolve(execPath, options.authRootCertFile); axiosConfig = setupQRSConnection(options, { method: 'get', fileCert, fileCertKey, + fileCertCA, path: `/qrs/task/full`, queryParameters: [{ name: 'filter', value: encodeURI(`id eq ${taskId}`) }], }); @@ -245,6 +253,7 @@ export async function deleteReloadTaskById(taskId, optionsParam) { // Expand cert file paths const fileCert = path.resolve(execPath, options.authCertFile); const fileCertKey = path.resolve(execPath, options.authCertKeyFile); + const fileCertCA = path.resolve(execPath, options.authRootCertFile); // Make sure certificate files exist on disk if (!fs.existsSync(fileCert)) { @@ -261,6 +270,7 @@ export async function deleteReloadTaskById(taskId, optionsParam) { method: 'delete', fileCert, fileCertKey, + fileCertCA, path: `/qrs/reloadtask/${taskId}`, }); } else if (optionsParam.authType === 'jwt') { @@ -315,6 +325,7 @@ export async function deleteExternalProgramTaskById(taskId, optionsParam) { // Expand cert file paths const fileCert = path.resolve(execPath, options.authCertFile); const fileCertKey = path.resolve(execPath, options.authCertKeyFile); + const fileCertCA = path.resolve(execPath, options.authRootCertFile); // Make sure certificate files exist on disk if (!fs.existsSync(fileCert)) { @@ -331,6 +342,7 @@ export async function deleteExternalProgramTaskById(taskId, optionsParam) { method: 'delete', fileCert, fileCertKey, + fileCertCA, path: `/qrs/externalprogramtask/${taskId}`, }); } else if (optionsParam.authType === 'jwt') {