From abe80128b1a5f38fb443edb24253c39d8f03bfda Mon Sep 17 00:00:00 2001 From: Ed Date: Mon, 4 Nov 2024 08:17:15 -0500 Subject: [PATCH] Improve error handling, RTR permission handling, and hide RTR interface when disabled --- components/crowdstrike-block.js | 5 +++ integration.js | 72 +++++++++++++++++++++++++++------ package-lock.json | 2 +- package.json | 2 +- src/realTimeResponse.js | 2 +- templates/crowdstrike-block.hbs | 18 +++++---- 6 files changed, 78 insertions(+), 23 deletions(-) diff --git a/components/crowdstrike-block.js b/components/crowdstrike-block.js index ae477a5..e6f4114 100644 --- a/components/crowdstrike-block.js +++ b/components/crowdstrike-block.js @@ -119,6 +119,11 @@ polarity.export = PolarityComponent.extend({ console.error(err); this.set('state.rtr.connectionStatus', 'Disconnected'); this.set('state.rtr.isConnected', false); + let errorMsg = err.detail; + if (!errorMsg) { + errorMsg = JSON.stringify(err, null, 2); + } + this.addConsoleMessage('error', errorMsg); }) .finally(() => { this.set('state.rtr.isConnecting', false); diff --git a/integration.js b/integration.js index 97dd903..dd4958d 100644 --- a/integration.js +++ b/integration.js @@ -126,6 +126,14 @@ const onMessage = async (payload, options, callback) => { switch (payload.action) { case 'GET_RTR_SESSION': try { + if (!options.enableRealTimeResponse) { + callback({ + detail: 'Real Time Response is disabled', + status: 401 + }); + return; + } + const { deviceId, platform } = payload; const { sessionId, pwd } = await getRtrSession(deviceId, options); @@ -148,13 +156,23 @@ const onMessage = async (payload, options, callback) => { customScripts }); } catch (error) { - const err = parseErrorToReadableJSON(error); - Logger.error(err, 'onMessage GET_RTR_SESSION Error'); - callback(err); + Logger.error({ error }, 'onMessage GET_RTR_SESSION Error'); + if(error.meta && Array.isArray(error.meta.errors) && error.meta.errors.length > 0){ + error.detail = `${error.meta.errors[0].message} (Code: ${error.meta.errors[0].code})`; + } + callback(error); } break; case 'DELETE_RTR_SESSION': try { + if (!options.enableRealTimeResponse) { + callback({ + detail: 'Real Time Response is disabled', + status: 401 + }); + return; + } + const { sessionId } = payload; await deleteRtrSession(sessionId, options); callback(null, { @@ -163,14 +181,24 @@ const onMessage = async (payload, options, callback) => { } catch (error) { // specifically look for a session timeout error if (!handleExpiredRtrSession(error, callback)) { - const err = parseErrorToReadableJSON(error); - Logger.error(err, 'onMessage DELETE_RTR_SESSION Error'); - callback(err); + Logger.error({ error }, 'onMessage DELETE_RTR_SESSION Error'); + if(error.meta && Array.isArray(error.meta.errors) && error.meta.errors.length > 0){ + error.detail = `${error.meta.errors[0].message} (Code: ${error.meta.errors[0].code})`; + } + callback(error); } } break; case 'RUN_SCRIPT': try { + if (!options.enableRealTimeResponse) { + callback({ + detail: 'Real Time Response is disabled', + status: 401 + }); + return; + } + const { sessionId, deviceId, baseCommand, commandString } = payload; if (!isEnabledScriptOrCommand(commandString, options)) { @@ -197,14 +225,24 @@ const onMessage = async (payload, options, callback) => { } catch (error) { // specifically look for a session timeout error if (!handleExpiredRtrSession(error, callback)) { - const err = parseErrorToReadableJSON(error); - Logger.error(err, 'onMessage RUN_SCRIPT Error'); - callback(err); + Logger.error({ error }, 'onMessage RUN_SCRIPT Error'); + if(error.meta && Array.isArray(error.meta.errors) && error.meta.errors.length > 0){ + error.detail = `${error.meta.errors[0].message} (Code: ${error.meta.errors[0].code})`; + } + callback(error); } } break; case 'GET_RTR_RESULT': try { + if (!options.enableRealTimeResponse) { + callback({ + detail: 'Real Time Response is disabled', + status: 401 + }); + return; + } + const { cloudRequestId, sequenceId } = payload; const { stdout, @@ -225,14 +263,24 @@ const onMessage = async (payload, options, callback) => { } catch (error) { // specifically look for a session timeout error if (!handleExpiredRtrSession(error, callback)) { - const err = parseErrorToReadableJSON(error); - Logger.error(err, 'onMessage GET_RTR_RESULT Error'); - callback(err); + Logger.error({ error }, 'onMessage GET_RTR_RESULT Error'); + if(error.meta && Array.isArray(error.meta.errors) && error.meta.errors.length > 0){ + error.detail = `${error.meta.errors[0].message} (Code: ${error.meta.errors[0].code})`; + } + callback(error); } } break; case 'containOrUncontain': try { + if (!options.allowContainment) { + callback({ + detail: 'Host containment is disabled', + status: 401 + }); + return; + } + const containedHost = await containHost(data, options); callback(null, containedHost); } catch (containError) { diff --git a/package-lock.json b/package-lock.json index 9a03a03..39c8ced 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "crowdstrike", - "version": "3.7.0", + "version": "3.7.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 6b2c181..8dc62c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "crowdstrike", - "version": "3.7.0", + "version": "3.7.1", "main": "./integration.js", "private": true, "license": "MIT", diff --git a/src/realTimeResponse.js b/src/realTimeResponse.js index 643aa98..8ed4bfb 100644 --- a/src/realTimeResponse.js +++ b/src/realTimeResponse.js @@ -294,7 +294,7 @@ const didRtrOptionsChange = (options) => { }; const maybeCacheRealTimeResponseScripts = async (options) => { - if (didRtrOptionsChange(options)) { + if (options.enableRealTimeResponse && didRtrOptionsChange(options)) { cachedFalconScripts = await getFalconScripts(options); cachedCustomScripts = await getCustomScripts(options); } diff --git a/templates/crowdstrike-block.hbs b/templates/crowdstrike-block.hbs index e7aa609..e42fafa 100644 --- a/templates/crowdstrike-block.hbs +++ b/templates/crowdstrike-block.hbs @@ -69,14 +69,16 @@ Host Management - + {{#if block.userOptions.enableRealTimeResponse}} + + {{/if}} {{/if}} {{/unless}}