From 160d3fe3ad6e2e1aaeec04dcd09890a81c66854b Mon Sep 17 00:00:00 2001 From: Anar Azadaliyev Date: Tue, 7 Nov 2017 00:17:28 +0200 Subject: [PATCH 1/9] add new commands to arcsight esm and fix fetch issues - fixed some fetch issues - fixed undefined issues - added new commands to arcsight - some of the commands using rest api instead of xml - fetch works much more faster now --- Integrations/integration-ArcSightESM.yml | 1181 +++++++++++++++------- 1 file changed, 840 insertions(+), 341 deletions(-) diff --git a/Integrations/integration-ArcSightESM.yml b/Integrations/integration-ArcSightESM.yml index 5a1f90beff3..aa5c0e172bb 100644 --- a/Integrations/integration-ArcSightESM.yml +++ b/Integrations/integration-ArcSightESM.yml @@ -66,54 +66,154 @@ script: script: |- var server = params.server.replace(/[\/]+$/, '') + ':' + params.port + '/'; - var sendRequest = function(url, args, login) { + var pathDictionary = { + login: 'www/core-service/rest/LoginService/login', + logout: 'www/core-service/rest/LoginService/logout', + 'as-get-matrix-data': 'www/manager-service/rest/QueryViewerService/getMatrixData', + 'as-get-all-cases': 'www/manager-service/rest/CaseService/findAllIds', + 'as-get-case': 'www/manager-service/rest/CaseService/getResourceById', + 'as-get-all-query-viewers': 'www/manager-service/rest/QueryViewerService/findAllIds', + 'as-get-case-event-ids': 'www/manager-service/rest/CaseService/getCaseEventIDs', + ActiveListService: 'www/manager-service/services/ActiveListService/' + }; + + function getToken() { + var res = JSON.parse(sendRequest( + pathDictionary.login, { + login: params.credentials.identifier, + password: params.credentials.password + }, + true)); + + if (res && res['log.loginResponse'] && res['log.loginResponse']['log.return']) { + return res['log.loginResponse']['log.return']; + } + + throw 'Failed to login. Check username/password. Original login response: ' + res; + } + + function logout() { + sendRequest(pathDictionary.logout, { + authToken: args.authToken + }); + } + + function sendRequest(url, args, login) { + var newArgs = args || {}; + newArgs.alt = 'json'; + + var fullUrl = server + url + encodeToURLQuery(newArgs); var res = http( - server + url + encodeToURLQuery(args), - { - Method: 'GET', - Headers: {'Content-Type': ['application/x-www-form-urlencoded']} - }, - params.insecure, - params.proxy - ); + fullUrl, { + Method: 'GET', + Headers: { + 'Content-Type': ['application/x-www-form-urlencoded'], + 'Accept': ['application/json'] + } + }, + params.insecure, + params.proxy + ); + if (res.StatusCode < 200 || res.StatusCode >= 300) { if (!login) { - sendRequest(pathDictionary.logout, {authToken: args.authToken}); + sendRequest(pathDictionary.logout, { + authToken: args.authToken + }); } - throw 'Request to ArcSight ' + url + ' failed, request status code: ' + res.StatusCode + ' and Body: ' + res.Body + '.'; + throw 'Request to ArcSight ' + fullUrl + ' failed, request status code: ' + res.StatusCode + ' and Body: ' + res.Body + '.'; } return res.Body; - }; + } - var sendAndParse = function(command, url, args) { + function sendAndParse(command, url, args) { + var json = parseSOAPResponse(sendRequest(url, args)); + if (!json) { + return null; + } - var json = parseSOAPResponse(sendRequest(url, args)); - if (!json) { - return 'No Data in response'; - } + var result = json; + return result; + } - var result = json; - if (command === 'as-get-all-cases') { - result = { - Type: entryTypes.note, - ContentsFormat: formats.json, - Contents: json, - ReadableContensFormat: formats.markdown, - HumanReadable: arrayToMarkdownTable(json, 'Case ID') - }; - } else if (translateTable[command]) { - result = { - Type: entryTypes.note, - ContentsFormat: formats.json, - Contents: json, - ReadableContensFormat: formats.markdown, - HumanReadable: tableToMarkdown('Something', convertByMap(json.return, translateTable[command])) - }; - } + function postRestRequest(queryPath, param, body) { + var stringBody = body; + if (body && typeof body !== 'string') { + stringBody = JSON.stringify(body) + } - return result; - }; + var newArgs = param || {}; + newArgs.alt = 'json'; + + // prepare the request url (make sure to encode the query parameter value) + var requestUrl = server + queryPath; + if (newArgs) { + requestUrl += encodeToURLQuery(newArgs); + } + + var res = http( + requestUrl, { + Method: 'POST', + Headers: { + 'Content-Type': ['application/json'], + 'Accept': ['application/json'] + }, + Body: stringBody + }, + params.insecure, + params.useproxy + ); + + if (res.StatusCode < 200 || res.StatusCode >= 300) { + throw 'Request Body: ' + stringBody + '\n' + 'Request Failed to ' + requestUrl + '.\nStatus code: ' + res.StatusCode + '.\nBody: ' + JSON.stringify(res) + '.'; + } + return res; + } + + function sendSOAPRequest(queryPath, param, body) { + // prepare the request url (make sure to encode the query parameter value) + var requestUrl = server + queryPath; + if (param) { + requestUrl += encodeToURLQuery(param); + } + + var res = http( + requestUrl, { + Method: 'POST', + Body: body + }, + params.insecure, + params.proxy + ); + + if (res.StatusCode < 200 || res.StatusCode >= 300) { + throw 'Request Failed to ' + requestUrl + '.\nStatus code: ' + res.StatusCode + '.\nBody: ' + JSON.stringify(res) + '.'; + } + + return res; + } + + function parseSOAPResponse(resBody) { + var matches = resBody.match(/(.|[\r\n])*<\/ns\d{1,3}:return>/); + if (!matches || !matches[0]) { + return null; + } + + var match = matches[0].replace(/:return>##==##==#(.+)<\/ns3:return>/.exec(sendRequest( - pathDictionary.login, - { - login: params.credentials.identifier, - password: params.credentials.password - }, - true)); - return match.length >= 2 && match[1]; + function convertRowsToStruct(fields, rows) { + var data = []; + for (var i = 0; i < rows.length; i++) { + var newData = {}; + for (var j = 0; j < fields.length; j++) { + if (rows[i].value[j]['#text']) { + newData[fields[j]] = rows[i].value[j]['#text']; + } + } + data.push(newData); + } + return data; } - function getCasesIncidents(lastRun) { - var newIncidents = []; - var existingIds = lastRun && lastRun.caseIds ? lastRun.caseIds : {}; - var response; - try { - response = sendAndParse(pathDictionary['as-get-all-cases'], args)['findAllIdsResponse']['return']; - } catch (ex) { - throw 'response to get all cases is not in the correct format'; - } - - if (!Array.isArray(response)) { - response = [response]; - } - for (var i = 0; i < response.length; i++) { - if (!existingIds[response[i]]) { - existingIds[response[i]] = true; - args.resourceId = response[i]; - var data = sendAndParse(pathDictionary['as-get-case'], args)['getResourceByIdResponse']['return']; - var keys = Object.keys(data); - var labels = []; - for (var j = 0; j%column%', { column: column })); - }) + stringBuilder.push(replaceInTemplates('%column%', { + column: column + })); + }); + entryList.entryList.forEach(function(entryRow) { stringBuilder.push(''); entryRow.forEach(function(entry) { - stringBuilder.push(replaceInTemplates('%entry%', { entry: entry })); + stringBuilder.push(replaceInTemplates('%entry%', { + entry: entry + })); }) stringBuilder.push(''); - }) + }); var entryListXml = stringBuilder.join(''); - var soapReq = replaceInTemplates(addEntriesTemplate, { authToken: args.authToken, resourceId: args.resourceId, entryList: entryListXml }); + var soapReq = replaceInTemplates(addEntriesTemplate, { + authToken: args.authToken, + resourceId: args.resourceId, + entryList: entryListXml + }); sendSOAPRequest('www/manager-service/services/ActiveListService/', null, soapReq); return 'Success'; } var clearEntriesTemplate = '%authToken%%resourceId%'; + function clearEntries() { - var soapReq = replaceInTemplates(clearEntriesTemplate, { authToken: args.authToken, resourceId: args.resourceId }); + var soapReq = replaceInTemplates(clearEntriesTemplate, { + authToken: args.authToken, + resourceId: args.resourceId + }); var res = sendSOAPRequest('www/manager-service/services/ActiveListService/', null, soapReq); return 'Success'; } - var getEntriesTemplate = ''+ - ''+ - ''+ - ''+ - '%authToken%'+ - '%resourceId%'+ - ''+ - ''+ - ''; + var getEntriesTemplate = '\ + \ + \ + \ + %authToken%\ + %resourceId%\ + \ + \ + '; + function getEntries() { - var soapReq = replaceInTemplates(getEntriesTemplate, { authToken: args.authToken, resourceId: args.resourceId }); + var soapReq = replaceInTemplates(getEntriesTemplate, { + authToken: args.authToken, + resourceId: args.resourceId + }); var res = sendSOAPRequest('www/manager-service/services/ActiveListService/', null, soapReq); - var entryArray = convertFromEntryListToCsvJSON(parseSOAPResponse(res.Body)); + var parsedResponse = parseSOAPResponse(res.Body); + var entryArray = convertFromEntryListToJSON(parsedResponse); + + // get the column headers which exists in Active List + var columns = dq(parsedResponse, 'return.columns'); + if (columns && !Array.isArray(columns)) { + columns = [columns]; + } + if (args.entryFilter) { var filteredEntries = []; var conditions = args.entryFilter.split(':'); @@ -397,195 +686,333 @@ script: } entryArray = filteredEntries; } + + var entryContext = {}; + entryContext['ArcSightESM.ActiveList.' + args.resourceId] = entryArray; + return [ + { + Type: entryTypes.note, + ContentsFormat: formats.json, + Contents: { + columns: columns + }, + ReadableContentsFormat: formats.markdown, + HumanReadable: columns ? arrayToMarkdownTable(columns, 'Columns') : 'Active list has no columns' + }, + { + Type: entryTypes.note, + ContentsFormat: formats.json, + Contents: { + result: entryArray + }, + ReadableContentsFormat: formats.markdown, + HumanReadable: (!entryArray || entryArray.length) ? tableToMarkdown('Active List Entries: ' + args.resourceId, entryArray) : 'Active List has no entries', + EntryContext: entryContext + } + ]; + } + + + function getCaseEventIDs() { + var json = JSON.parse(sendRequest(pathDictionary['as-get-case-event-ids'], args)); + if (!json || !json['cas.getCaseEventIDsResponse'] || !json['cas.getCaseEventIDsResponse']['cas.return']) { + return null; + } + + var eventIds = json['cas.getCaseEventIDsResponse']['cas.return']; + if (!eventIds) { + // case has no events + return null; + } + + if (!Array.isArray(eventIds)) { + eventIds = [eventIds]; + } + var entryContext = {}; + entryContext['ArcSightESM.CaseEvents'] = eventIds; + return { + Type: entryTypes.note, + ContentsFormat: formats.json, + Contents: json, + ReadableContentsFormat: formats.markdown, + HumanReadable: arrayToMarkdownTable(eventIds, 'Case ' + args.caseId + ' Event IDs'), + EntryContext: entryContext + }; + } + + function updateCase() { + var currentCase = getCaseRequest(args.authToken, args.caseId); + if (!currentCase) { + throw 'There is no such case: ' + args.caseId; + } + + var updatedCase = currentCase; + updatedCase.stage = args.stage; + var soapReq = { + 'cas.update': { + 'cas.authToken': args.authToken, + 'cas.resource': updatedCase + } + }; + try { + var res = postRestRequest('www/manager-service/rest/CaseService/update', null, soapReq); + } catch (err) { + throw 'soapReq: ' + soapReq + '\n' + err; + } + + // creating human readable table + var response = JSON.parse(res.Body) + + if (!response || !response['cas.updateResponse'] || !response['cas.updateResponse']['cas.return']) { + return null; + } + + var responseUpdatedCase = response['cas.updateResponse']['cas.return']; + var entryContext = {}; + entryContext['ArcSightESM.Cases(val.resourceid===obj.resourceid)'] = responseUpdatedCase; return { - Type: entryTypes.note, - ContentsFormat: formats.json, - Contents: { result: entryArray }, - ReadableContentsFormat: formats.markdown, - HumanReadable: tableToMarkdown('Active List ' + args.resourceId, entryArray) + Type: entryTypes.note, + ContentsFormat: formats.json, + Contents: responseUpdatedCase, + ReadableContensFormat: formats.markdown, + HumanReadable: tableToMarkdown('Case ' + args.caseId, convertByMap(responseUpdatedCase, { + 'Name': 'name', + 'EventIDs': 'eventIDs', + 'Action': 'action', + 'Stage': 'stage', + 'CaseID': 'resourceid', + 'CreatedTime': 'createdTimestamp=Date(val)' + })), + EntryContext: entryContext }; } - var getMonitorDataTemplate = ''+ - '%authToken%'+ - '%monitorID%'+ - ''+ - '%monitorID%'+ - '%modificationCount%'+ - ''+ - ''; - - var monitorDataTemplateWithEnv =''+ - ''+ - '' + - getMonitorDataTemplate + - '' + - ''; - - function getDataMonitor(authToken, modCount, monitorID){ - var soapReq = replaceInTemplates(monitorDataTemplateWithEnv, { authToken:authToken, modificationCount : modCount, monitorID : monitorID}); - var res = sendSOAPRequest('www/manager-service/services/DataMonitorService/', null, soapReq); - return res.Body; + function deleteCase() { + var reqBody = { + 'cas.deleteByUUID': { + 'cas.authToken': args.authToken, + 'cas.id': args.caseId + } + }; + + try { + var res = postRestRequest('www/manager-service/rest/CaseService/deleteByUUID', null, reqBody); + } catch (err) { + throw 'soapReq: ' + reqBody + '\n' + err; + } + + throw res; } - var getSecurityEventsTemplate = ''+ - ''+ - ''+ - ''+ - '%authToken%'+ - '%ids%'+ - '%startMillis%'+ - '%endMillis%'+ - ''+ - ''+ - ''; - - var intToIpDT = ';function intToIP(int){' + - 'var part1 = int & 255;'+ - 'var part2 = ((int >> 8) & 255);'+ - 'var part3 = ((int >> 16) & 255);'+ - 'var part4 = ((int >> 24) & 255);'+ - 'return part4 + "." + part3 + "." + part2 + "." + part1;'+ - '};'; + var intToIpDT = ';function intToIP(int){\ + var part1 = int & 255;\ + var part2 = ((int >> 8) & 255);\ + var part3 = ((int >> 16) & 255);\ + var part4 = ((int >> 24) & 255);\ + return part4 + "." + part3 + "." + part2 + "." + part1;\ + };'; // table from JSON to human readable table var eventTranslateMap = { - 'Time' : 'endTime=new Date(Number(val)).toLocaleString()' + 'Event ID': 'eventId', + 'Time': 'endTime=new Date(Number(val)).toLocaleString()', 'Source Address': 'source.address=intToIP(val)' + intToIpDT, 'Destination Address': 'destination.address=intToIP(val)' + intToIpDT, 'Name': 'name', - 'source Port': 'source.port' - + 'Source Port': 'source.port', + 'Base Event IDs': 'baseEventIds' }; - function getSecurityEvents(){ - var startMillis = args.startMillis || '0'; - var endMillis = args.endMillis || ((new Date().getTime()) + 100000) + ''; + function getSecurityEvents() { + var events = getSecurityEventsRequest(args.authToken, args.ids, args.startDate, args.endDate); + var hr = 'No events found'; + if (events) { + hr = tableToMarkdown('Security Event: ' + args.ids, convertByMap(events, eventTranslateMap)) + } - var soapReq = replaceInTemplates(getSecurityEventsTemplate, { authToken: args.authToken, ids: args.ids, startMillis: startMillis, endMillis: endMillis }); - var res = sendSOAPRequest('www/manager-service/services/SecurityEventService/', null, soapReq); + var entryContext = {}; + entryContext['ArcSightESM.SecurityEvents(val.eventId===obj.eventId)'] = events; + return { + Type: entryTypes.note, + ContentsFormat: formats.json, + Contents: { events: events }, + ReadableContentsFormat: formats.markdown, + HumanReadable: hr, + EntryContext: entryContext + }; + } - // creating human readable table - var parsedEvents = parseSOAPResponse(res.Body) - if (!parsedEvents || !parsedEvents.return) { - return 'No events found'; + function getSecurityEventsRequest(authToken, ids, startDate, endDate) { + var startMillis = -1; + if (startDate) { + if (isNaN(Date.parse(startDate))) { + throw 'startDate must be of format yyyy-mm-ddTHH:MM:SS. Example: 2015-09-22T10:00:00'; + } + startMillis = new Date(startDate).getTime(); + } + var endMillis = -1; + if (endDate) { + if (isNaN(Date.parse(endDate))) { + throw 'endDate must be of format yyyy-mm-ddTHH:MM:SS. Example: 2015-09-22T10:00:00'; + } + endMillis = new Date(endDate).getTime(); } - var events = parsedEvents.return; - if (!Array.isArray(events)) { - events = [events]; + var arrIDs = []; + var split = ids.split(','); + for (var i = 0; i < split.length; i++) { + var id = split[i]; + if (isNaN(id)) { + throw 'id ' + id + ' must be numeric'; + } + arrIDs.push(parseInt(id)); } - return { - Type: entryTypes.note, - ContentsFormat: formats.json, - Contents: { result: events }, - ReadableContentsFormat: formats.markdown, - HumanReadable: tableToMarkdown('Security Event', convertByMap(events, eventTranslateMap)) + var soapReq = { + 'sev.getSecurityEvents': { + 'sev.authToken': authToken, + 'sev.ids': arrIDs, + 'sev.startMillis': startMillis, + 'sev.endMillis': endMillis + } }; - } + var res = postRestRequest('www/manager-service/rest/SecurityEventService/getSecurityEvents', null, soapReq); - var getDashboardDataTemplate = ''+ - '%authToken%'+ - '%monitorID%'+ - ''+ - '%monitorID%'+ - '%modificationCount%'+ - ''+ - ''; - - var dashboardDataTemplateWithEnv =''+ - ''+ - '' + - getDashboardDataTemplate + - '' + - ''; + // creating human readable table + var json = JSON.parse(res.Body); + if (!json || !json['sev.getSecurityEventsResponse'] || !json['sev.getSecurityEventsResponse']['sev.return']) { + return null; + } - // currently this function is not works - function getDashboardData(authToken, modCount, monitorID){ - var soapReq = replaceInTemplates(dashboardDataTemplateWithEnv, { authToken:authToken, modificationCount : modCount, monitorID : monitorID}); - //return soapReq; - var res = sendSOAPRequest('www/manager-service/services/DashboardService/', null, soapReq); - return res.Body; - } + var events = json['sev.getSecurityEventsResponse']['sev.return']; - function sendSOAPRequest(queryPath, param, body) { - // prepare the request url (make sure to encode the query parameter value) - var requestUrl = server + queryPath; - if (param) { - requestUrl += encodeToURLQuery(param); + if (!Array.isArray(events)) { + events = [events]; } - var res = http( - requestUrl, - { - Method: 'POST', - Body: body - }, - params.insecure, - params.proxy - ); + return events; + } - if (res.StatusCode < 200 || res.StatusCode >= 300) { - throw 'Request Failed to ' + requestUrl + '.\nStatus code: ' + res.StatusCode + '.\nBody: ' + JSON.stringify(res) + '.'; - } - return res; + var dashboardDataTemplateWithEnv = '\ + \ + \ + \ + %authToken%\ + %monitorID%\ + \ + %monitorID%\ + %modificationCount%\ + \ + \ + \ + '; + + // currently this function is not works + function getDashboardData(authToken, modCount, monitorID) { + var soapReq = replaceInTemplates(dashboardDataTemplateWithEnv, { + authToken: authToken, + modificationCount: modCount, + monitorID: monitorID + }); + //return soapReq; + var res = postRestRequest('www/manager-service/services/DashboardService/', null, soapReq); + return res.Body; } - function parseSOAPResponse(resBody) { - var matches = resBody.match(/(.|[\r\n])*<\/ns\d{1,3}:return>/); - if (!matches) { - return null; - } - - var match = matches[0].replace(/:return>##==##==#\ + \ + \ + \ + %authToken%\ + %monitorID%\ + \ + %monitorID%\ + %modificationCount%\ + \ + \ + \ + '; + + function getDataMonitor(authToken, modCount, monitorID) { + var soapReq = replaceInTemplates(monitorDataTemplateWithEnv, { + authToken: authToken, + modificationCount: modCount, + monitorID: monitorID + }); + var res = postRestRequest('www/manager-service/services/DataMonitorService/', null, soapReq); + return res.Body; } + var result; + args.authToken = getToken(); switch (command) { - case 'test-module': - sendRequest(pathDictionary.logout, args); - return 'ok'; - case 'fetch-incidents': - var lastRun = getLastRun(); - lastRun = lastRun && lastRun.value ? JSON.parse(lastRun.value) : {}; - var casesIncidents = []; - var eventsIncidents = []; - if (params.importCases) { - casesIncidents = getCasesIncidents(lastRun); - } - if (params.importEvents) { - eventsIncidents = getEventsIncidents(lastRun); - } - setLastRun({value: JSON.stringify(lastRun)}); - return JSON.stringify(casesIncidents.concat(eventsIncidents)); - case 'as-add-entries': - return addEntries(); - case 'as-clear-entries': - return clearEntries(); - case 'as-get-entries': - return getEntries(); - case 'as-get-security-events': - return getSecurityEvents(args.authToken, args.ids, args.startTime, args.endTime); - default: - return sendAndParse(command, pathDictionary[command], args); + case 'test-module': + sendRequest(pathDictionary.logout, args); + result = 'ok'; + break; + case 'fetch-incidents': + var lastRun = getLastRun(); + lastRun = lastRun && lastRun.value ? JSON.parse(lastRun.value) : {}; + var casesIncidents = []; + var eventsIncidents = []; + if (params.importCases) { + casesIncidents = getCasesIncidents(lastRun); + } + if (params.importEvents) { + eventsIncidents = getEventsIncidents(lastRun); + } + setLastRun({ + value: JSON.stringify(lastRun) + }); + result = JSON.stringify(casesIncidents.concat(eventsIncidents)); + break; + case 'as-get-matrix-data': + result = getMatrixData(); + break; + case 'as-get-all-cases': + result = getAllCases(); + break; + case 'as-get-all-query-viewers': + result = getAllQueryViewers(); + break; + case 'as-get-case': + result = getCase(); + break; + case 'as-add-entries': + result = addEntries(); + break; + case 'as-clear-entries': + result = clearEntries(); + break; + case 'as-get-entries': + result = getEntries(); + break; + case 'as-get-security-events': + result = getSecurityEvents(); + break; + case 'as-get-case-event-ids': + result = getCaseEventIDs(); + break; + case 'as-update-case': + result = updateCase(); + break; + case 'as-case-delete': + result = deleteCase(); + break; + default: + result = sendAndParse(command, pathDictionary[command], args); } + logout(); + return result; type: javascript commands: - name: as-get-all-cases arguments: [] + outputs: + - contextPath: ArcSightESM.AllCaseIDs + description: All cases ids description: commands.server.arcsight.getallcases.description - name: as-get-case arguments: @@ -593,6 +1020,15 @@ script: required: true default: true description: commands.server.arcsight.arguments.caseid.description + outputs: + - contextPath: ArcSightESM.Cases.resourceid + description: The id of the case + - contextPath: ArcSightESM.Cases.name + description: Name of the case + - contextPath: ArcSightESM.Cases.eventIDs + description: Related base event ids + - contextPath: ArcSightESM.Cases.createdTimestamp + description: The time case created description: commands.server.arcsight.getspecificcase.description - name: as-get-matrix-data arguments: @@ -600,31 +1036,94 @@ script: required: true default: true description: commands.server.arcsight.arguments.queryid.description + - name: onlyColumns + auto: PREDEFINED + predefined: + - "true" + - "false" + defaultValue: "true" description: commands.server.arcsight.query.description - name: as-add-entries arguments: - name: resourceId required: true + description: resource id of the Active list - name: entries required: true + description: 'Entries in JSON format. JSON must be array of entries. Each entry + must contain the same columns like in the Active list. Example: [{ "UserName": + "john", "IP":"19.12.13.11"},{ "UserName": "bob", "IP":"22.22.22.22"}]' isArray: true + description: Add new entries to Active List execution: true - name: as-clear-entries arguments: - name: resourceId required: true + description: resource id of Active list + description: Clean all entries in the Active List execution: true - name: as-get-entries arguments: - name: resourceId required: true + description: resource id of Active list - name: entryFilter - description: 'OPTIONAL. Filters the entries. Example: entryFilter="moo:moo1"' + description: 'Filters the entries. Example: entryFilter="moo:moo1"' + outputs: + - contextPath: ArcSightESM.ActiveList + description: Active List is a map of active list resource id => active list + entries + description: Get all entries from Active List - name: as-get-security-events arguments: - - name: startTime - - name: endTime + - name: startDate + description: 'Start time filter. Example: 2017-05-22T10:00:00' + - name: endDate + description: 'End time filter. Example: 2017-05-22T10:00:00' - name: ids required: true + outputs: + - contextPath: ArcSightESM.SecurityEvents + description: List of security events + - contextPath: ArcSightESM.SecurityEvents.name + description: The name of the event + - contextPath: ArcSightESM.SecurityEvents.eventId + description: Event id + - contextPath: ArcSightESM.SecurityEvents.type + description: Type of the event + - contextPath: ArcSightESM.SecurityEvents.baseEventIds + description: Base event ids + - contextPath: ArcSightESM.SecurityEvents.startTime + description: Start time in milliseconds + - name: as-get-case-event-ids + arguments: + - name: caseId + required: true + outputs: + - contextPath: ArcSightESM.CaseEvents + description: Map of caseId => related event ids + - contextPath: ArcSightESM.CaseEvents.LatestResult + description: Event ids of the last execution of this command + - name: as-update-case + arguments: + - name: caseId + required: true + - name: stage + outputs: + - contextPath: ArcSightESM.Cases + description: List of cases + - name: as-get-all-query-viewers + arguments: [] + outputs: + - contextPath: ArcSightESM.AllQueryViewers + description: List of all query viewer ids + description: Returns all the query viewer ids + - name: as-case-delete + arguments: + - name: caseId + required: true + description: The resource id of the case + execution: true isfetch: true -hidden: false +releaseNotes: 'Added new commands, fixed fetching bugs' From eae2f45049ef13835f7f0c19bba7f5d6e5964ba3 Mon Sep 17 00:00:00 2001 From: Anar Azadaliyev Date: Tue, 7 Nov 2017 00:44:26 +0200 Subject: [PATCH 2/9] fixed test --- Integrations/integration-ArcSightESM.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/Integrations/integration-ArcSightESM.yml b/Integrations/integration-ArcSightESM.yml index aa5c0e172bb..f494600451d 100644 --- a/Integrations/integration-ArcSightESM.yml +++ b/Integrations/integration-ArcSightESM.yml @@ -949,7 +949,6 @@ script: args.authToken = getToken(); switch (command) { case 'test-module': - sendRequest(pathDictionary.logout, args); result = 'ok'; break; case 'fetch-incidents': From 4339d1352ecff6a4ed21b00c637cd1188a40da59 Mon Sep 17 00:00:00 2001 From: Anar Azadaliyev Date: Tue, 7 Nov 2017 19:52:12 +0200 Subject: [PATCH 3/9] fixed fetch --- Integrations/integration-ArcSightESM.yml | 146 ++++++++++++++--------- 1 file changed, 87 insertions(+), 59 deletions(-) diff --git a/Integrations/integration-ArcSightESM.yml b/Integrations/integration-ArcSightESM.yml index f494600451d..c64fb989ce8 100644 --- a/Integrations/integration-ArcSightESM.yml +++ b/Integrations/integration-ArcSightESM.yml @@ -22,29 +22,31 @@ configuration: defaultvalue: "" type: 9 required: true -- display: Import events as incidents - name: importEvents - defaultvalue: "" - type: 8 - required: false -- display: Events query viewer ID +- display: Fetch Events as incidents via Query Viewer ID. Mandatory fields for query + are Start Time and Event ID. name: viewerId defaultvalue: "" type: 0 required: false -- display: Time field for query - name: timeField +- display: Fetch Cases as incidents via Query Viewer ID. Mandatory fields for query + are Create Time and ID. + name: casesQueryViewerId defaultvalue: "" type: 0 required: false -- display: Import cases as incidents - name: importCases +- display: Fetch incidents + name: isFetch defaultvalue: "" type: 8 required: false +- display: Incident type + name: incidentType + defaultvalue: "" + type: 13 + required: false - display: Do not validate server certificate (insecure) name: insecure - defaultvalue: "" + defaultvalue: "true" type: 8 required: false - display: Use system proxy settings @@ -52,16 +54,6 @@ configuration: defaultvalue: "false" type: 8 required: false -- display: Fetch incidents - name: isFetch - defaultvalue: "" - type: 8 - required: false -- display: Incident type - name: incidentType - defaultvalue: "" - type: 13 - required: false script: script: |- var server = params.server.replace(/[\/]+$/, '') + ':' + params.port + '/'; @@ -259,71 +251,81 @@ script: } function getCasesIncidents(lastRun) { + var timeField = 'Create Time'; // Query must contain Start Time field var newIncidents = []; - var allCaseIDs; - var existingCases = (lastRun && lastRun.existingCases) ? lastRun.existingCases : {}; + var response; try { - allCaseIDs = getAllCasesRequest(args.authToken); + response = getQueryViewerResultsRequest(args.authToken, params.casesQueryViewerId, false); } catch (ex) { - throw 'allCaseIDs to get all cases is not in the correct format. Error: ' + ex; + throw 'Cases response to query is not in the correct format. Error: ' + ex; } - - if (!Array.isArray(allCaseIDs)) { - allCaseIDs = [allCaseIDs]; + if (!response) { + throw 'Cases response to query is empty'; } - for (var i = 0; i < allCaseIDs.length; i++) { - var resourceId = allCaseIDs[i]; - if (!existingCases[resourceId]) { - // we add only cases which not exists in the last run - var newCase = getCaseRequest(args.authToken, resourceId); + var fieldNames = response.columnHeaders; + if (fieldNames.indexOf(timeField) === -1) { + throw 'Cases Query must contain ' + timeField + ' fields'; + } + var data = response.data; - var keys = Object.keys(newCase); + var lastEventTime = (lastRun && lastRun.caseLastEventTime) ? lastRun.caseLastEventTime : 0; + var maxEventTime = lastEventTime; + for (var i = 0; i < data.length; i++) { + var eventTimeInMillis = Number(data[i][timeField]); + if (lastEventTime < eventTimeInMillis) { + if (maxEventTime < eventTimeInMillis) { + maxEventTime = eventTimeInMillis; + } + var keys = Object.keys(data[i]); var labels = []; for (var j = 0; j < keys.length; j++) { if (keys[j] !== 'Name') { labels.push({ - 'type': keys[j], - 'value': String(newCase[keys[j]]) + type: keys[j], + value: String(data[i][keys[j]]) }); } } newIncidents.push({ - name: newCase.Name || ('New event from arcsight at ' + Date.now()), + name: data[i].Name || ('New case from arcsight at ' + Date.now()), labels: labels, - rawJSON: JSON.stringify(newCase) + rawJSON: JSON.stringify(data[i]) }); - - existingCases[resourceId] = true; } } - lastRun.existingCases = existingCases; + lastRun.caseLastEventTime = maxEventTime; return newIncidents; } - function getEventsIncidents(lastRun) { + var timeField = 'Start Time'; // Query must contain Start Time field var newIncidents = []; - // args.id = params.viewerId; + var response; try { - response = getQueryViewerResultsRequest(args.authToken, params.viewerId, true); + response = getQueryViewerResultsRequest(args.authToken, params.viewerId, false); } catch (ex) { - throw 'response to query is not in the correct format. Error: ' + ex; + throw 'Events response to query is not in the correct format. Error: ' + ex; } if (!response) { - throw 'response to query is empty'; + throw 'Events response to query is empty'; } var fieldNames = response.columnHeaders; - if (fieldNames.indexOf(params.timeField) === -1) { - throw 'time field is missing in query response'; + if (fieldNames.indexOf(timeField) === -1) { + throw 'Events Query must contain ' + timeField + ' fields'; } - var data = convertRowsToStruct(fieldNames, response.rows); + var data = response.data; var lastEventTime = lastRun && lastRun.lastEventTime ? lastRun.lastEventTime : 0; + var maxEventTime = lastEventTime; for (var i = 0; i < data.length; i++) { - if (lastEventTime < data[i][params.timeField]) { - lastRun.lastEventTime = data[i][params.timeField]; + var eventTimeInMillis = Number(data[i][timeField]); + if (lastEventTime < eventTimeInMillis) { + if (maxEventTime < eventTimeInMillis) { + maxEventTime = eventTimeInMillis; + } + var keys = Object.keys(data[i]); var labels = []; for (var j = 0; j < keys.length; j++) { @@ -342,7 +344,7 @@ script: } } - delete(args.id); + lastRun.lastEventTime = maxEventTime; return newIncidents; } @@ -397,9 +399,18 @@ script: return null; } + function dlog(obj) { + try { + log(JSON.stringify(obj, null, 2)); + } catch (err) { + log(obj); + } + + } + function getMatrixData() { - args.onlyHeaders = args.onlyHeaders === 'true' ? true : false; - var results = getQueryViewerResultsRequest(args.authToken, args.id, args.onlyHeaders); + args.onlyColumns = args.onlyColumns === 'true' ? true : false; + var results = getQueryViewerResultsRequest(args.authToken, args.id, args.onlyColumns); var entries = [{ Type: entryTypes.note, @@ -409,14 +420,14 @@ script: HumanReadable: arrayToMarkdownTable(results.columnHeaders, 'Column Headers') // will print only query viewer column headers }]; - if (!args.onlyHeaders) { + if (!args.onlyColumns) { entries.push({ Type: entryTypes.note, ContentsFormat: formats.json, Contents: results.data, ReadableContensFormat: formats.markdown, HumanReadable: tableToMarkdown('Query Viewer Results: ' + args.id, results.data) // will print all the results table - }) + }); } return entries; @@ -432,6 +443,9 @@ script: if (json && json['qvs.getMatrixDataResponse'] && json['qvs.getMatrixDataResponse']['qvs.return']) { var returnObject = json['qvs.getMatrixDataResponse']['qvs.return']; var columnHeaders = dq(returnObject, 'columnHeaders'); + if (columnHeaders && !Array.isArray(columnHeaders)) { + columnHeaders = [columnHeaders]; + } if (includeOnlyHeaders) { return { columnHeaders: columnHeaders @@ -956,12 +970,13 @@ script: lastRun = lastRun && lastRun.value ? JSON.parse(lastRun.value) : {}; var casesIncidents = []; var eventsIncidents = []; - if (params.importCases) { + if (params.casesQueryViewerId) { casesIncidents = getCasesIncidents(lastRun); } - if (params.importEvents) { + if (params.viewerId) { eventsIncidents = getEventsIncidents(lastRun); } + setLastRun({ value: JSON.stringify(lastRun) }); @@ -1095,6 +1110,7 @@ script: description: Base event ids - contextPath: ArcSightESM.SecurityEvents.startTime description: Start time in milliseconds + description: Returns the security event details - name: as-get-case-event-ids arguments: - name: caseId @@ -1104,14 +1120,25 @@ script: description: Map of caseId => related event ids - contextPath: ArcSightESM.CaseEvents.LatestResult description: Event ids of the last execution of this command + description: Returns all case event IDs - name: as-update-case arguments: - name: caseId required: true + description: The ID of the case - name: stage + auto: PREDEFINED + predefined: + - CLOSED + - QUEUED + - FINAL + - FOLLOW_UP + - INITIAL + description: The stage of case outputs: - contextPath: ArcSightESM.Cases description: List of cases + description: Updates a case - name: as-get-all-query-viewers arguments: [] outputs: @@ -1123,6 +1150,7 @@ script: - name: caseId required: true description: The resource id of the case + description: Deletes a case execution: true isfetch: true -releaseNotes: 'Added new commands, fixed fetching bugs' +releaseNotes: '-' \ No newline at end of file From 14a4f356d58abcfad0d276f9c802f411abcc0fd3 Mon Sep 17 00:00:00 2001 From: Anar Azadaliyev Date: Tue, 7 Nov 2017 20:51:10 +0200 Subject: [PATCH 4/9] test will validate mandatory fields --- Integrations/integration-ArcSightESM.yml | 46 ++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/Integrations/integration-ArcSightESM.yml b/Integrations/integration-ArcSightESM.yml index c64fb989ce8..9f6a188164e 100644 --- a/Integrations/integration-ArcSightESM.yml +++ b/Integrations/integration-ArcSightESM.yml @@ -58,6 +58,12 @@ script: script: |- var server = params.server.replace(/[\/]+$/, '') + ':' + params.port + '/'; + // Arcsight field names + var eventIdField = 'Event ID'; + var caseIdField = 'ID'; + var eventsTimeField = 'Start Time'; + var casesTimeField = 'Create Time'; + var pathDictionary = { login: 'www/core-service/rest/LoginService/login', logout: 'www/core-service/rest/LoginService/logout', @@ -959,10 +965,50 @@ script: return res.Body; } + function test() { + var isFetch = params.isFetch; + if (isFetch && !params.viewerId && !params.casesQueryViewerId) { + throw 'If Fetch incidents is on, then Events Query Viewer ID or Case Query Viewer ID must be passed'; + } + + var results; + var columnHeaders + if (isFetch && params.viewerId) { + try { + results = getQueryViewerResultsRequest(args.authToken, params.viewerId, true); + } catch(ex) { + throw 'Make sure Events query viewer id is valid.\nOriginal Error: ' + ex; + } + columnHeaders = results.columnHeaders; + if (columnHeaders.indexOf(eventsTimeField) === -1) { + throw 'Event Query in ArcSight must select "' + eventsTimeField + '" field'; + } + if (columnHeaders.indexOf(eventIdField) === -1) { + throw 'Event Query in ArcSight must select "' + eventIdField + '" field'; + } + } + + if (isFetch && params.casesQueryViewerId) { + try { + results = getQueryViewerResultsRequest(args.authToken, params.casesQueryViewerId, true); + } catch(ex) { + throw 'Make sure Cases query viewer id is valid.\nOriginal Error: ' + ex; + } + columnHeaders = results.columnHeaders; + if (columnHeaders.indexOf(casesTimeField) === -1) { + throw 'Case Query in ArcSight must select "' + casesTimeField + '" field'; + } + if (columnHeaders.indexOf(caseIdField) === -1) { + throw 'Case Query in ArcSight must select "' + caseIdField + '" field'; + } + } + } + var result; args.authToken = getToken(); switch (command) { case 'test-module': + test(); result = 'ok'; break; case 'fetch-incidents': From 2fe995b550f73475d36924bac3b6cb8f1dab8edb Mon Sep 17 00:00:00 2001 From: Anar Azadaliyev Date: Thu, 9 Nov 2017 19:33:45 +0200 Subject: [PATCH 5/9] fix https://github.com/demisto/server/issues/9716 --- Integrations/integration-ArcSightESM.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Integrations/integration-ArcSightESM.yml b/Integrations/integration-ArcSightESM.yml index 9f6a188164e..3618efa6fdd 100644 --- a/Integrations/integration-ArcSightESM.yml +++ b/Integrations/integration-ArcSightESM.yml @@ -879,13 +879,15 @@ script: } var arrIDs = []; - var split = ids.split(','); - for (var i = 0; i < split.length; i++) { - var id = split[i]; - if (isNaN(id)) { - throw 'id ' + id + ' must be numeric'; - } - arrIDs.push(parseInt(id)); + if (typeof ids === 'string') { + var split = ids.split(','); + for (var i = 0; i < split.length; i++) { + var id = split[i]; + if (isNaN(id)) { + throw 'id ' + id + ' must be numeric'; + } + arrIDs.push(parseInt(id)); + } } var soapReq = { From b3940105252d0a946a1484ee4cb3a7e9a07acf2c Mon Sep 17 00:00:00 2001 From: liorkol Date: Sun, 12 Nov 2017 01:20:27 +0200 Subject: [PATCH 6/9] Arcsight ESM - Get case data playbook --- ...sight_-_Get_events_related_to_the_Case.yml | 308 ++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 Playbooks/playbook-Arcsight_-_Get_events_related_to_the_Case.yml diff --git a/Playbooks/playbook-Arcsight_-_Get_events_related_to_the_Case.yml b/Playbooks/playbook-Arcsight_-_Get_events_related_to_the_Case.yml new file mode 100644 index 00000000000..b2166317ca0 --- /dev/null +++ b/Playbooks/playbook-Arcsight_-_Get_events_related_to_the_Case.yml @@ -0,0 +1,308 @@ +id: Arcsight - Get events related to the Case +version: -1 +name: Arcsight - Get events related to the Case +description: |- + Get the Case's Arcsight ResourceID from the ArcsightCaseID field, or the "ID" label. If neither is there, ask user for the ID. + Use the resource ID to get full data for the case, the correlated/aggregate events underneath it, and all base events underneath them. +starttaskid: "0" +tasks: + "0": + id: "0" + taskid: 607a5cb3-f71b-4fe2-8ca8-c7799c2ed832 + type: start + task: + id: 607a5cb3-f71b-4fe2-8ca8-c7799c2ed832 + version: -1 + name: "" + iscommand: false + brand: "" + nexttasks: + '#none#': + - "4" + view: |- + { + "position": { + "x": 425, + "y": -659 + } + } + "1": + id: "1" + taskid: 99d98b0d-51ee-4819-8bb1-9580ca71c8b8 + type: regular + task: + id: 99d98b0d-51ee-4819-8bb1-9580ca71c8b8 + version: -1 + name: Arcsight - Get Case info + description: Get a specific case from ESM + script: ArcSight ESM|||as-get-case + type: regular + iscommand: true + brand: ArcSight ESM + scriptarguments: + resourceId: ${incident.arcsightcaseid} + view: |- + { + "position": { + "x": 567, + "y": 380 + } + } + "2": + id: "2" + taskid: 93787e94-68ef-4646-8a86-82c128f9892a + type: regular + task: + id: 93787e94-68ef-4646-8a86-82c128f9892a + version: -1 + name: Arcsight - get Event ID below the Case + description: Returns all case event IDs + script: ArcSight ESM|||as-get-case-event-ids + type: regular + iscommand: true + brand: ArcSight ESM + nexttasks: + '#none#': + - "3" + scriptarguments: + caseId: ${incident.arcsightcaseid} + view: |- + { + "position": { + "x": 89, + "y": 380 + } + } + "3": + id: "3" + taskid: 03be188a-b48c-467c-8879-cf89a3b5ea65 + type: regular + task: + id: 03be188a-b48c-467c-8879-cf89a3b5ea65 + version: -1 + name: Get the Events below the Case + script: ArcSight ESM|||as-get-security-events + type: regular + iscommand: true + brand: ArcSight ESM + nexttasks: + '#none#': + - "10" + scriptarguments: + endDate: "" + ids: ${ArcSightESM.CaseEvents} + startDate: "" + view: |- + { + "position": { + "x": 89, + "y": 571 + } + } + "4": + id: "4" + taskid: 7f654da8-0f7a-4007-8f75-36ebd9296cdd + type: condition + task: + id: 7f654da8-0f7a-4007-8f75-36ebd9296cdd + version: -1 + name: Is ArcsightCaseID set? + scriptName: Exists + type: condition + iscommand: false + brand: "" + nexttasks: + '#default#': + - "5" + "yes": + - "9" + scriptarguments: + value: ${incident.arcsightcaseid} + view: |- + { + "position": { + "x": 425, + "y": -509 + } + } + "5": + id: "5" + taskid: f0248d07-ced8-4878-8dce-af05d1c46b4c + type: condition + task: + id: f0248d07-ced8-4878-8dce-af05d1c46b4c + version: -1 + name: Is ID label included? + scriptName: Exists + type: condition + iscommand: false + brand: "" + nexttasks: + '#default#': + - "7" + "yes": + - "6" + scriptarguments: + value: ${incident.labels.ID} + view: |- + { + "position": { + "x": 106, + "y": -321 + } + } + "6": + id: "6" + taskid: 9b9c88f9-39da-4e55-8fee-648b67a11e12 + type: regular + task: + id: 9b9c88f9-39da-4e55-8fee-648b67a11e12 + version: -1 + name: Set ArcsightCaseID <-- ID label + scriptName: IncidentSet + type: regular + iscommand: false + brand: "" + nexttasks: + '#none#': + - "9" + scriptarguments: + addLabels: "" + customFieldName: ArcsightCaseID + customFieldValue: ${incident.labels.ID} + details: "" + labels: "" + name: "" + owner: "" + playbook: "" + severity: "" + stage: "" + type: "" + updatePlaybookForType: "" + view: |- + { + "position": { + "x": 269, + "y": -108 + } + } + "7": + id: "7" + taskid: 2b6d2ec9-c419-46fe-8a9c-badc467ba746 + type: regular + task: + id: 2b6d2ec9-c419-46fe-8a9c-badc467ba746 + version: -1 + name: User - please insert Arcsight Case Resource ID + scriptName: Set + type: regular + iscommand: false + brand: "" + nexttasks: + '#none#': + - "8" + scriptarguments: + append: "" + key: UserInput.ArcsightCaseID + value: "" + view: |- + { + "position": { + "x": -140, + "y": -108 + } + } + "8": + id: "8" + taskid: c9b44c59-36cd-4906-8113-ef2c93553faf + type: regular + task: + id: c9b44c59-36cd-4906-8113-ef2c93553faf + version: -1 + name: Set ArcsightCaseID from user input + scriptName: IncidentSet + type: regular + iscommand: false + brand: "" + nexttasks: + '#none#': + - "9" + scriptarguments: + addLabels: "" + customFieldName: ArcsightCaseID + customFieldValue: ${UserInput.ArcsightCaseID} + details: "" + labels: "" + name: "" + owner: "" + playbook: "" + severity: "" + stage: "" + type: "" + updatePlaybookForType: "" + view: |- + { + "position": { + "x": -140, + "y": 57 + } + } + "9": + id: "9" + taskid: d722aebc-ddc2-4022-8577-e88f8869585d + type: title + task: + id: d722aebc-ddc2-4022-8577-e88f8869585d + version: -1 + name: Get case and event info + type: title + iscommand: false + brand: "" + nexttasks: + '#none#': + - "2" + - "1" + view: |- + { + "position": { + "x": 328, + "y": 231 + } + } + "10": + id: "10" + taskid: 31770e39-9146-473d-8111-c0af16c1c582 + type: regular + task: + id: 31770e39-9146-473d-8111-c0af16c1c582 + version: -1 + name: Get Base Events below the top-level event + script: ArcSight ESM|||as-get-security-events + type: regular + iscommand: true + brand: ArcSight ESM + scriptarguments: + endDate: "" + ids: ${ArcSightESM.SecurityEvents.baseEventIds} + startDate: "" + view: |- + { + "position": { + "x": 89, + "y": 766 + } + } +view: |- + { + "linkLabelsPosition": {}, + "paper": { + "dimensions": { + "height": 1520, + "width": 1087, + "x": -140, + "y": -659 + } + } + } +inputs: [] +releaseNotes: "First version added" \ No newline at end of file From f2ef86864d57803f277fffef1c4247ddf1b44d76 Mon Sep 17 00:00:00 2001 From: Anar Azadaliyev Date: Sun, 12 Nov 2017 09:30:10 +0200 Subject: [PATCH 7/9] add release notes in order to fix the build --- Integrations/integration-ArcSightESM.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Integrations/integration-ArcSightESM.yml b/Integrations/integration-ArcSightESM.yml index 3618efa6fdd..fb1a076f8ba 100644 --- a/Integrations/integration-ArcSightESM.yml +++ b/Integrations/integration-ArcSightESM.yml @@ -1201,4 +1201,9 @@ script: description: Deletes a case execution: true isfetch: true -releaseNotes: '-' \ No newline at end of file +releaseNotes: 'Added new commands +- as-case-delete +- as-get-all-query-viewers +- as-get-case-event-ids + +There is no need for ArcSight XML integration, fetch can be done via ArcSight ESM' From 65f4934ad9af5997469eb6934cedaa259599ed94 Mon Sep 17 00:00:00 2001 From: Anar Azadaliyev Date: Sun, 12 Nov 2017 10:11:33 +0200 Subject: [PATCH 8/9] fix security event ids --- Integrations/integration-ArcSightESM.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Integrations/integration-ArcSightESM.yml b/Integrations/integration-ArcSightESM.yml index fb1a076f8ba..5880f0ec612 100644 --- a/Integrations/integration-ArcSightESM.yml +++ b/Integrations/integration-ArcSightESM.yml @@ -888,6 +888,10 @@ script: } arrIDs.push(parseInt(id)); } + } else if (typeof ids === 'number') { + // ids passed as number + // so there only single id + arrIDs.push(ids); } var soapReq = { From 58a7754d466022b2e4943baf048dce60340f3db0 Mon Sep 17 00:00:00 2001 From: liorkol Date: Sun, 12 Nov 2017 18:19:24 +0200 Subject: [PATCH 9/9] Playbook - Arcsight get events - Added checks for event IDs in context and using standard FetchID field. --- ...sight_-_Get_events_related_to_the_Case.yml | 171 +++++++++++++----- 1 file changed, 125 insertions(+), 46 deletions(-) diff --git a/Playbooks/playbook-Arcsight_-_Get_events_related_to_the_Case.yml b/Playbooks/playbook-Arcsight_-_Get_events_related_to_the_Case.yml index b2166317ca0..4304ac86455 100644 --- a/Playbooks/playbook-Arcsight_-_Get_events_related_to_the_Case.yml +++ b/Playbooks/playbook-Arcsight_-_Get_events_related_to_the_Case.yml @@ -2,16 +2,16 @@ id: Arcsight - Get events related to the Case version: -1 name: Arcsight - Get events related to the Case description: |- - Get the Case's Arcsight ResourceID from the ArcsightCaseID field, or the "ID" label. If neither is there, ask user for the ID. + Get the Case's Arcsight ResourceID from the FetchID field, or the "ID" label. If neither is there, ask user for the ID. Use the resource ID to get full data for the case, the correlated/aggregate events underneath it, and all base events underneath them. starttaskid: "0" tasks: "0": id: "0" - taskid: 607a5cb3-f71b-4fe2-8ca8-c7799c2ed832 + taskid: d042890c-556f-415a-8b61-a12119407553 type: start task: - id: 607a5cb3-f71b-4fe2-8ca8-c7799c2ed832 + id: d042890c-556f-415a-8b61-a12119407553 version: -1 name: "" iscommand: false @@ -28,10 +28,10 @@ tasks: } "1": id: "1" - taskid: 99d98b0d-51ee-4819-8bb1-9580ca71c8b8 + taskid: b5d1bb23-5f5f-47a9-88b2-c61071cf4468 type: regular task: - id: 99d98b0d-51ee-4819-8bb1-9580ca71c8b8 + id: b5d1bb23-5f5f-47a9-88b2-c61071cf4468 version: -1 name: Arcsight - Get Case info description: Get a specific case from ESM @@ -39,21 +39,24 @@ tasks: type: regular iscommand: true brand: ArcSight ESM + nexttasks: + '#none#': + - "12" scriptarguments: - resourceId: ${incident.arcsightcaseid} + resourceId: ${incident.FetchID} view: |- { "position": { - "x": 567, + "x": 328, "y": 380 } } "2": id: "2" - taskid: 93787e94-68ef-4646-8a86-82c128f9892a + taskid: 687fd65f-c25d-448c-8d7b-02dca8a3f7e0 type: regular task: - id: 93787e94-68ef-4646-8a86-82c128f9892a + id: 687fd65f-c25d-448c-8d7b-02dca8a3f7e0 version: -1 name: Arcsight - get Event ID below the Case description: Returns all case event IDs @@ -63,22 +66,22 @@ tasks: brand: ArcSight ESM nexttasks: '#none#': - - "3" + - "11" scriptarguments: - caseId: ${incident.arcsightcaseid} + caseId: ${incident.FetchID} view: |- { "position": { - "x": 89, + "x": -140, "y": 380 } } "3": id: "3" - taskid: 03be188a-b48c-467c-8879-cf89a3b5ea65 + taskid: b5fab90a-0f15-40ba-8233-43ed42be978c type: regular task: - id: 03be188a-b48c-467c-8879-cf89a3b5ea65 + id: b5fab90a-0f15-40ba-8233-43ed42be978c version: -1 name: Get the Events below the Case script: ArcSight ESM|||as-get-security-events @@ -87,7 +90,7 @@ tasks: brand: ArcSight ESM nexttasks: '#none#': - - "10" + - "13" scriptarguments: endDate: "" ids: ${ArcSightESM.CaseEvents} @@ -95,18 +98,18 @@ tasks: view: |- { "position": { - "x": 89, - "y": 571 + "x": -372, + "y": 763 } } "4": id: "4" - taskid: 7f654da8-0f7a-4007-8f75-36ebd9296cdd + taskid: 3371774c-a2ba-4ea3-8acb-aaeeae8195f7 type: condition task: - id: 7f654da8-0f7a-4007-8f75-36ebd9296cdd + id: 3371774c-a2ba-4ea3-8acb-aaeeae8195f7 version: -1 - name: Is ArcsightCaseID set? + name: Is FetchID set? scriptName: Exists type: condition iscommand: false @@ -117,7 +120,7 @@ tasks: "yes": - "9" scriptarguments: - value: ${incident.arcsightcaseid} + value: ${incident.FetchID} view: |- { "position": { @@ -127,10 +130,10 @@ tasks: } "5": id: "5" - taskid: f0248d07-ced8-4878-8dce-af05d1c46b4c + taskid: a8d523d4-a25e-45a9-8553-fccb9b49d585 type: condition task: - id: f0248d07-ced8-4878-8dce-af05d1c46b4c + id: a8d523d4-a25e-45a9-8553-fccb9b49d585 version: -1 name: Is ID label included? scriptName: Exists @@ -153,12 +156,12 @@ tasks: } "6": id: "6" - taskid: 9b9c88f9-39da-4e55-8fee-648b67a11e12 + taskid: 295f3a37-e590-40a5-8093-a71aa5386c74 type: regular task: - id: 9b9c88f9-39da-4e55-8fee-648b67a11e12 + id: 295f3a37-e590-40a5-8093-a71aa5386c74 version: -1 - name: Set ArcsightCaseID <-- ID label + name: Set FetchID <-- ID label scriptName: IncidentSet type: regular iscommand: false @@ -168,7 +171,7 @@ tasks: - "9" scriptarguments: addLabels: "" - customFieldName: ArcsightCaseID + customFieldName: FetchID customFieldValue: ${incident.labels.ID} details: "" labels: "" @@ -188,10 +191,10 @@ tasks: } "7": id: "7" - taskid: 2b6d2ec9-c419-46fe-8a9c-badc467ba746 + taskid: 00fc9870-1af2-47d1-828b-24dbbd6f02cc type: regular task: - id: 2b6d2ec9-c419-46fe-8a9c-badc467ba746 + id: 00fc9870-1af2-47d1-828b-24dbbd6f02cc version: -1 name: User - please insert Arcsight Case Resource ID scriptName: Set @@ -203,7 +206,7 @@ tasks: - "8" scriptarguments: append: "" - key: UserInput.ArcsightCaseID + key: UserInput.FetchID value: "" view: |- { @@ -214,12 +217,12 @@ tasks: } "8": id: "8" - taskid: c9b44c59-36cd-4906-8113-ef2c93553faf + taskid: 2b66e9f0-4a63-47d3-80d2-41da31835e0b type: regular task: - id: c9b44c59-36cd-4906-8113-ef2c93553faf + id: 2b66e9f0-4a63-47d3-80d2-41da31835e0b version: -1 - name: Set ArcsightCaseID from user input + name: Set FetchID from user input scriptName: IncidentSet type: regular iscommand: false @@ -229,8 +232,8 @@ tasks: - "9" scriptarguments: addLabels: "" - customFieldName: ArcsightCaseID - customFieldValue: ${UserInput.ArcsightCaseID} + customFieldName: FetchID + customFieldValue: ${UserInput.FetchID} details: "" labels: "" name: "" @@ -249,10 +252,10 @@ tasks: } "9": id: "9" - taskid: d722aebc-ddc2-4022-8577-e88f8869585d + taskid: c2788a78-f0a8-488e-887b-428e224ceaac type: title task: - id: d722aebc-ddc2-4022-8577-e88f8869585d + id: c2788a78-f0a8-488e-887b-428e224ceaac version: -1 name: Get case and event info type: title @@ -271,16 +274,19 @@ tasks: } "10": id: "10" - taskid: 31770e39-9146-473d-8111-c0af16c1c582 + taskid: 65602a3e-3b1f-4134-80f1-7f056a937775 type: regular task: - id: 31770e39-9146-473d-8111-c0af16c1c582 + id: 65602a3e-3b1f-4134-80f1-7f056a937775 version: -1 name: Get Base Events below the top-level event script: ArcSight ESM|||as-get-security-events type: regular iscommand: true brand: ArcSight ESM + nexttasks: + '#none#': + - "12" scriptarguments: endDate: "" ids: ${ArcSightESM.SecurityEvents.baseEventIds} @@ -288,21 +294,94 @@ tasks: view: |- { "position": { - "x": 89, - "y": 766 + "x": -626, + "y": 1110 + } + } + "11": + id: "11" + taskid: 29025200-cf8e-4d69-80f1-166eb6b3a034 + type: condition + task: + id: 29025200-cf8e-4d69-80f1-166eb6b3a034 + version: -1 + name: Does Case included IDs for related Events? + scriptName: Exists + type: condition + iscommand: false + brand: "" + nexttasks: + '#default#': + - "12" + "yes": + - "3" + scriptarguments: + value: ${ArcSightESM.CaseEvents} + view: |- + { + "position": { + "x": -140, + "y": 560 + } + } + "12": + id: "12" + taskid: 5c12898b-66b7-4400-8ff9-f7c3632c007a + type: title + task: + id: 5c12898b-66b7-4400-8ff9-f7c3632c007a + version: -1 + name: Done + type: title + iscommand: false + brand: "" + view: |- + { + "position": { + "x": 187, + "y": 1299 + } + } + "13": + id: "13" + taskid: 6b37cdf2-9072-49ae-848c-ea00e953a603 + type: condition + task: + id: 6b37cdf2-9072-49ae-848c-ea00e953a603 + version: -1 + name: Do we have IDs for underlying base events? + scriptName: Exists + type: condition + iscommand: false + brand: "" + nexttasks: + '#default#': + - "12" + "yes": + - "10" + scriptarguments: + value: ${ArcSightESM.SecurityEvents.baseEventIds} + view: |- + { + "position": { + "x": -372, + "y": 924 } } view: |- { - "linkLabelsPosition": {}, + "linkLabelsPosition": { + "11_12_#default#": 0.1, + "13_12_#default#": 0.1 + }, "paper": { "dimensions": { - "height": 1520, - "width": 1087, - "x": -140, + "height": 2023, + "width": 1431, + "x": -626, "y": -659 } } } inputs: [] -releaseNotes: "First version added" \ No newline at end of file +releaseNotes: "Added checks for existence of event IDs in Context" \ No newline at end of file