Skip to content

Instantly share code, notes, and snippets.

@chrissmith-mcafee
Created October 3, 2018 22:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrissmith-mcafee/7f87ffc17134a60883b16d67dd91a836 to your computer and use it in GitHub Desktop.
Save chrissmith-mcafee/7f87ffc17134a60883b16d67dd91a836 to your computer and use it in GitHub Desktop.
This Node-RED flow executes a `McAfee Active Response` search for the running processes on a particular endpoint as specified by its IP address. The names of the processes found are retrieved and captured one page (up to 5 items) at a time.
[
{
"id": "15c35c35.087ac4",
"type": "tab",
"label": "MAR Basic Paging Example",
"disabled": false,
"info": "This sample executes a `McAfee Active Response` search for the running processes\r\non a particular endpoint as specified by its IP address. The names of the\r\nprocesses found are retrieved and captured one page (up to 5 items) at a time.\r\nThe resulting process names captured across all pages are displayed on the\r\nNode-RED `debug` tab.\r\n\r\n### Prerequisites\r\n\r\n* The samples configuration step has been completed (see\r\n [Client Configuration](https://opendxl.github.io/node-red-contrib-dxl/jsdoc/tutorial-configuration.html)).\r\n* A McAfee Active Response (MAR) service is available on the DXL fabric.\r\n* The DXL client associated with the\r\n`Search MAR for host` node has been authorized to perform MAR searches\r\n (see [Authorize Client to Perform MAR Search](https://opendxl.github.io/opendxl-client-python/pydoc/marsendauth.html)).\r\n\r\n### Setup\r\n\r\n* Edit the `Specify host to find` node and modify the `Payload` property with\r\n the IP address of a host to retrieve the process list from. For example:\r\n\r\n ```\r\n 192.168.1.1\r\n ```\r\n\r\n* To deploy the flow, press the `Deploy` button in the upper-right corner of the\r\n screen. If Node-RED is able to properly connect to the DXL fabric, a green dot\r\n with the word `connected` should appear under the `Search MAR for host` node.\r\n\r\n### Running\r\n\r\nTo exercise the flow, double-click the button on the left side of the\r\n`Specify host to find` node.\r\n\r\n### Output\r\n\r\nOutput similar to the following should appear in the Node-RED `debug` tab:\r\n\r\n```\r\n? [ array[5], array[5], array[5] ]\r\n```\r\n\r\nAfter clicking on the right arrow buttons to expand the contents of the array,\r\noutput similar to the following should appear:\r\n\r\n```\r\n? array[3]\r\n ? 0: array[5]\r\n 0: \"MARService.exe\"\r\n 1: \"OneDrive.exe\"\r\n 2: \"RuntimeBroker.exe\"\r\n 3: \"SearchIndexer.exe\"\r\n 4: \"SearchUI.exe\"\r\n ? 1: array[5]\r\n 0: \"ShellExperienceHost.exe\"\r\n 1: \"SkypeHost.exe\"\r\n 2: \"System\"\r\n 3: \"UpdaterUI.exe\"\r\n 4: \"VGAuthService.exe\"\r\n ? 2: array[5]\r\n 0: \"WUDFHost.exe\"\r\n 1: \"WmiApSrv.exe\"\r\n 2: \"WmiPrvSE.exe\"\r\n 3: \"WmiPrvSE.exe\"\r\n 4: \"[System Process]\"\r\n...\r\n```\r\n\r\n### Details\r\n\r\nThe flow exercises the nodes below.\r\n\r\n#### Specify host to find\r\n\r\nThis is an `inject` input node which starts the flow. This node injects a new\r\nmessage with a `payload` property which specifies the IP address of host to\r\nfind.\r\n\r\n#### Set search conditions\r\n\r\nThis is a `template` node which formats the IP address supplied on the\r\n`msg.payload` property by the `Specify host to find` node into the\r\n`conditions` property on the output message. The `Search MAR for host` node\r\nuses the `conditions` property when constructing the parameters for MAR\r\nsearch. \r\n\r\nThe JSON-formatted mustache template has the following:\r\n\r\n```json\r\n{\r\n \"or\": [{\r\n \"and\": [{\r\n \"name\": \"HostInfo\",\r\n \"output\": \"ip_address\",\r\n \"op\": \"EQUALS\",\r\n \"value\": \"{{payload}}\"\r\n }]\r\n }]\r\n}\r\n```\r\n\r\nIf the `payload` property on the input message, for example, were set to\r\n`192.168.1.1`, the resulting JavaScript object stored to the `conditions`\r\nproperty on the output message would be:\r\n\r\n```javascript\r\n{\r\n or: [{\r\n and: [{\r\n name: 'HostInfo',\r\n output: 'ip_address',\r\n op: 'EQUALS',\r\n value\": '192.168.1.1'\r\n }]\r\n }]\r\n}\r\n```\r\n\r\n#### Search MAR for host\r\n\r\nThis is a `mar search` node. This node connects to the DXL fabric and sends a\r\nsearch request to the MAR service to collect process information from a\r\nparticular system (as specified by the IP address in the `msg.conditions`\r\nproperty set by the `Set search conditions` node).\r\n\r\nThe JSON-formatted document provided for `Projections` property specifies that\r\n`Processes` for the target host should be returned:\r\n\r\n```json\r\n[\r\n {\r\n \"name\": \"Processes\"\r\n }\r\n]\r\n```\r\n\r\nThe `Limit` property specifies that up to the next \"5\" result items should be\r\nprovided per `page` of search results. This node is revisited repeatedly by the\r\n`More results available?` node until all of the result items available\r\nfor the search have been retrieved.\r\n\r\nThe `Sort by` and `Sort` properties, respectively, specify that the search\r\nresults should be sorted by the \"Processes|name\" field in \"Ascending\" order.\r\n\r\nThe `Return` property is set to \"a parsed JSON object\" to indicate that the\r\n`payload` for the response should be added to the output message as a JavaScript\r\nobject decoded from JSON.\r\n\r\n#### Extract process names\r\n\r\nThis is a `function` node. This node includes a JavaScript code snippet which\r\niterates over the search result items that were set on the `msg.payload`\r\nproperty by the `Search MAR for hosts` node. The source code for the code\r\nsnippet is included below:\r\n\r\n```javascript\r\nif (!msg.processes) {\r\n msg.processes = []\r\n}\r\n\r\nmsg.processes.push(\r\n msg.payload.map(function (processEntry) {\r\n return processEntry.output[\"Processes|name\"]\r\n })\r\n)\r\n\r\nreturn msg\r\n```\r\n\r\nAn array is assigned to the `processes` property in the message. Each element\r\nin the array contains an sub-array with the names of processes returned for\r\nthe previous page. New elements are appended to the array each time this node\r\nis revisited to capture a page of search results.\r\n\r\nFor example, the contents of the `processes` property after the first time this\r\nnode is visited within a flow might contain:\r\n\r\n```javascript\r\n[[\"MARService.exe\",\r\n \"OneDrive.exe\",\r\n \"RuntimeBroker.exe\",\r\n \"SearchIndexer.exe\", \r\n \"SearchUI.exe\"]]\r\n```\r\n\r\nAfter the second time this node is visited for a flow, the `processes` property\r\nmight contain:\r\n\r\n```javascript\r\n[[\"MARService.exe\",\r\n \"OneDrive.exe\",\r\n \"RuntimeBroker.exe\",\r\n \"SearchIndexer.exe\", \r\n \"SearchUI.exe\"],\r\n [\"ShellExperienceHost.exe\",\r\n \"SkypeHost.exe\",\r\n \"System\",\r\n \"UpdaterUI.exe\",\r\n \"VGAuthService.exe\"]]\r\n```\r\n\r\n#### More results available?\r\n\r\nThis is a `switch` node. This node routes the input message to a different\r\nnode based on the value of the `hasMoreItems` property.\r\n\r\nIf the value of `hasMoreItems` is `true`, additional items are available to be\r\nretrieved from the MAR server for the current search. In this case, the input\r\nmessage is routed back to the `Search MAR for host` node. When the\r\n`Search MAR for host` node is revisited, the next page of search results is\r\nobtained from the MAR server and forwarded along to the `Extract process names`\r\nnode.\r\n\r\nIf the value of `hasMoreItems` is `false`, no additional items are available\r\nto be retrieved from the MAR server for the current search. In this case, the\r\ninput message is routed to the `Output process names` node.\r\n\r\n#### Output process names\r\n\r\nThis is a `debug` output node. This node outputs the array of process names\r\nwritten by the `Extract process names` node to the `msg.processes` property\r\nfor each page of search results returned from the MAR server."
},
{
"id": "3fbfd464.d3a6cc",
"type": "inject",
"z": "15c35c35.087ac4",
"name": "Specify host to find",
"topic": "",
"payload": "<specify-host-ip-address>",
"payloadType": "str",
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"x": 130,
"y": 100,
"wires": [
[
"32c7d68f.2ed0ca"
]
]
},
{
"id": "53c77ace.c1e504",
"type": "switch",
"z": "15c35c35.087ac4",
"name": "More results available?",
"property": "hasMoreItems",
"propertyType": "msg",
"rules": [
{
"t": "true"
},
{
"t": "false"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 190,
"y": 400,
"wires": [
[
"b6e234bf.312e78"
],
[
"cd7c5168.252d9"
]
]
},
{
"id": "cd7c5168.252d9",
"type": "debug",
"z": "15c35c35.087ac4",
"name": "Debug: Output process names",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "processes",
"x": 490,
"y": 400,
"wires": []
},
{
"id": "2a2240df.31f3b",
"type": "function",
"z": "15c35c35.087ac4",
"name": "Extract process names",
"func": "if (!msg.processes) {\n msg.processes = []\n}\n\nmsg.processes.push(\n msg.payload.map(function (processEntry) {\n return processEntry.output[\"Processes|name\"]\n })\n)\n\nreturn msg",
"outputs": 1,
"noerr": 0,
"x": 480,
"y": 280,
"wires": [
[
"53c77ace.c1e504"
]
]
},
{
"id": "b6e234bf.312e78",
"type": "dxl-mar-search",
"z": "15c35c35.087ac4",
"name": "Search MAR for host",
"pollInterval": 5,
"client": "42926d46.783374",
"projections": "[\n {\n \"name\": \"Processes\"\n }\n]",
"limit": "5",
"textFilter": "",
"sortBy": "Processes|name",
"sortDirection": "asc",
"returnType": "obj",
"x": 440,
"y": 180,
"wires": [
[
"2a2240df.31f3b"
]
]
},
{
"id": "32c7d68f.2ed0ca",
"type": "template",
"z": "15c35c35.087ac4",
"name": "Set search conditions",
"field": "conditions",
"fieldType": "msg",
"format": "json",
"syntax": "mustache",
"template": "{\n \"or\": [{\n \"and\": [{\n \"name\": \"HostInfo\",\n \"output\": \"ip_address\",\n \"op\": \"EQUALS\",\n \"value\": \"{{payload}}\"\n }]\n }]\n}",
"output": "json",
"x": 200,
"y": 180,
"wires": [
[
"b6e234bf.312e78"
]
]
},
{
"id": "c271164f.62d8b8",
"type": "comment",
"z": "15c35c35.087ac4",
"name": "Supply the IP address of the host to find in the 'Specify host to find' node",
"info": "",
"x": 270,
"y": 40,
"wires": []
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment