Details
| ID | Core REST API |
|---|---|
| Provider | Palo Alto Networks |
| Category | Utilities |
| From Version | 5.0.0 |
| Supported Modules | Agentix Cortex Cloud Cloud Runtime Security Cloud Posture Security XSIAM EDR |
README
Configure Core REST API in Cortex
| Parameter | Description | Required |
|---|---|---|
| Core Server URL | For Cortex XSOAR 8 or Cortex XSIAM, use the Copy API URL button on the API Keys page. For Cortex XSOAR 6, use the server URL. | True |
| API Key ID | The API Key ID that is linked to the API Key (relevant for Cortex XSIAM and Cortex XSOAR 8.0.0 and above). | True |
| API Key (Password) | The core server API key. | True |
| Authentication method | Whether authentication should be using “Standard” API key or “Advanced” API key. | True |
| Base marketplace url | The base url for the tenant marketplace. | False |
| Trust any certificate (not secure) | Trust any certificate (not secure). | False |
| Use system proxy settings | Use system proxy settings. | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
Please Note: When updating or making changes to a custom content item (integration, script, list, etc.), it may be necessary to increment the version of the item. To do so, first fetch the current version (usually via a GET command) and then increment the version by 1. Lastly, when updating an item, please use this incremented value for the version field.
core-api-post
send HTTP POST request
Base Command
core-api-post
Input
| Argument Name | Description | Required |
|---|---|---|
| uri | Request endpoint (e.g. /incident or /public_api/v1/incidents/update_incident). | Required |
| body | Body of HTTP POST. | Optional |
Context Output
There is no context output for this command.
Command Example
!core-api-post uri=/lists/save body={\"name\":\"list_name\",\"data\":\"list_data\"}
Human Readable Output
{“response”:{“commitMessage”:””,”data”:”list_data”,”definitionId”:””,”description”:””,”fromServerVersion”:””,”id”:”list_name”,”itemVersion”:””,”locked”:false,”modified”:”2022-05-29T12:20:14.988577Z”,”name”:”list_name”,”nameLocked”:false,”packID”:””,”prevName”:”list_name”,”primaryTerm”:6,”propagationLabels”:[“all”],”sequenceNumber”:907233,”shouldCommit”:false,”system”:false,”tags”:null,”toServerVersion”:””,”truncated”:false,”type”:”plain_text”,”vcShouldIgnore”:false,”vcShouldKeepItemLegacyProdMachine”:false,”version”:1}}
core-api-get
send HTTP GET requests
Base Command
core-api-get
Input
| Argument Name | Description | Required |
|---|---|---|
| uri | Request endpoint (e.g. /user or /public_api/v1/rbac/get_users). | Required |
Context Output
There is no context output for this command.
Command Example
!core-api-get uri=/user
Human Readable Output
{“response”:{“addedSharedDashboards”:[“Threat Intelligence Feeds”,”Troubleshooting Instances”],”allRoles”:[“Administrator”],”defaultAdmin”:true,”email”:”admintest@core.com”,”id”:”admin”,”image”:”8327000###user_image_admin.png”,”lastLogin”:”2022-05-29T15:13:46.224432+03:00”,”name”:”Admin Dude”,”notificationsSettings”:{“email”:{“all”:true},”pushNotifications”:{“all”:true}},”permissions”:{“core”:[“scripts.rwx”,”playbooks.rw”]},”phone”:”+650-123456”,”playgroundId”:”beda-02ab-49ef-8fc1-c43a36f”}}
core-api-put
send HTTP PUT request
Base Command
core-api-put
Input
| Argument Name | Description | Required |
|---|---|---|
| uri | Request endpoint (e.g. /user). | Required |
| body | Request body. | Optional |
core-api-delete
send HTTP DELETE request
Base Command
core-api-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| uri | Request endpoint (e.g. /user). | Required |
Context Output
There is no context output for this command.
Command Example
!core-api-delete uri=/dashboards/9a6cc590-72bb-4ed5-84e9-4577c6d8cbb9
Human Readable Output
{“response”:””}
core-api-download
Download files from core server
Base Command
core-api-download
Input
| Argument Name | Description | Required |
|---|---|---|
| uri | Request endpoint. | Required |
| filename | File name of download. | Optional |
| description | Description of file entry. | Optional |
Context Output
There is no context output for this command.
Command Example
!core-api-download uri=/log/bundle
Context Example
{
"File": {
"EntryID": "yukswe2UVanMjyvEANmLBH@bed9ccda-02ab-49ef-8fc1-c43a",
"Extension": "gz",
"Info": "gz",
"MD5": "e4e0a23740dfaa27f00b276af",
"Name": "logs-bundle-29May2215_14IDT.tar.gz",
"SHA1": "95e0ebd554ea107f04508d6c2d9e6361",
"SHA256": "83032a86295279ecdf516b63eae7a7e3e5af301bf4dfed3c82faa23b58",
"SHA512": "88a3fa0194c7dd439c749b2b0b9cbef64ce18e469d0b8b62bcf18919ffcefd1c99119c993070454d48061357ff0dd0ffe0a070936b62c7ac35035de3",
"SSDeep": "98304:wAjPMXI9/8BoAKIxrVqJVAw6LgJEBFCH73LOOFdWgiwvSJdBo:3PmI9/8jKIxrVOELrCHwq7O",
"Size": 4052002,
"Type": "gzip compressed data, original size modulo 2^32 46240256"
}
}
Human Readable Output
core-api-multipart
Send HTTP Multipart request to upload files to Core server
Base Command
core-api-multipart
Input
| Argument Name | Description | Required |
|---|---|---|
| uri | Request endpoint. | Required |
| entryID | File entry ID. | Required |
| body | Request body. | Optional |
Context Output
There is no context output for this command.
Command Example
!core-api-multipart uri=/incident/upload/204 entryID=evnKTiujxaZEkeKRxiBMig@bed9ccda-02ab-49ef-8fc1-c43a36ff38f5 body=test_bark
Human Readable Output
{“response”:{“activated”:”0001-01-01T00:00:00Z”,”attachment”:[{“description”:””,”name”:”logs-bundle-29May2214_36IDT.tar.gz”,”path”:”204_34d-836b-4b38-81eb-9b90af9c1a_logs-bundle-29May2214_36IDT.tar.gz”,”showMediaFile”:false,”type”:”application/octet-stream”}],”autime”:1653651342394000,”closed”:”0001-01-01T00:00:00Z”,”created”:”2022-05-27T13:15:51.342394+03:00”,”dueDate”:”0001-01-01T00:00:00Z”,”id”:”204”,”labels”:[{“type”:”Brand”,”value”:”Grafana”},{“type”:”Instance”,”value”:”Grafana_instance_1”}],”modified”:”2022-05-29T12:20:17.196279Z”,”name”:”Adi’s Alert”,”numericId”:204,”occurred”:”2022-05-27T02:02:30Z”,”rawName”:”Adi’s Alert”,”rawType”:”Grafana Alert”,”sequenceNumber”:545,”sourceBrand”:”Grafana”,”sourceInstance”:”Grafana_instance_1”,”type”:”Grafana Alert”,”version”:2}}
core-delete-incidents
Delete Core incidents
Base Command
core-delete-incidents
Input
| Argument Name | Description | Required |
|---|---|---|
| ids | IDs of the incidents to delete. | Required |
Context Output
There is no context output for this command.
Command Example
!core-delete-incidents ids=152
Human Readable Output
Core delete incidents
totalDeleted total notUpdated 1 143 0
core-api-install-packs
Upload packs to Core server from url or the marketplace.
Base Command
core-api-install-packs
Input
| Argument Name | Description | Required |
|---|---|---|
| packs_to_install | The packs to install in JSON format (e.g. [{“AutoFocus”: “2.0.8”}] ). | Optional |
| file_url | The pack zip file url. | Optional |
| entry_id | The War Room entry ID of the pack zip file. | Optional |
| skip_verify | If true will skip pack signature validation, Available from 6.5.0 server version. | Optional |
| skip_validation | If true will skip all pack validations, Available from 6.6.0 server version. | Optional |
| timeout_in_seconds | The request timeout in seconds. Default value is 180 (3 minutes). | Optional |
Context Output
There is no context output for this command.
Command Example
!core-api-install-packs packs_to_install=[{"AutoFocus": "2.0.8"}]
Human Readable Output
The following packs installed successfully: AutoFocus
core-api-file-upload
Upload to the incident a file that the user provided according to the entry_id or the content of the file.
Base Command
core-api-file-upload
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The incident’s ID. | Required |
| file_name | The new file’s name. | Optional |
| file_content | The new file’s content. | Optional |
| entry_id | The War Room entry ID of the pack zip file. | Optional |
Context Output
There is no context output for this command.
core-api-file-delete
Delete a war room (investigation) file entry.
Base Command
core-api-file-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| entry_id | The War Room entry ID of the file. | Required |
Context Output
There is no context output for this command.
core-api-file-attachment-delete
Delete a file attachment from an incident — specifically from the incident’s file attachments (not from the war room).
Base Command
core-api-file-attachment-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The incident’s ID. | Required |
| file_path | The file’s path. | Required |
| field_name | Name of the field (type attachment) from which to remove the attachment. Default is attachment. | Optional |
Command example
!core-api-file-attachment-delete file_path=1@1 incident_id=1
Human Readable Output
Attachment 1@1 deleted.
core-api-file-check
Check if the file exists in Cortex XSOAR (Context) by entry_id.
Base Command
core-api-file-check
Input
| Argument Name | Description | Required |
|---|---|---|
| entry_id | The War Room entry ID of the file. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| IsFileExists | unknown | Dictionary with EntryID as the key and boolean if the file exists as a value. |
Configuration parameters
url— Core Server URL (required)creds_apikey— API Key IDauth_method— Authentication methodmarketplace_url— Base marketplace urlinsecure— Trust any certificate (not secure)proxy— Use system proxy settingsuse_tenant— Use tenant
Commands (20)
-
core-api-deletesend HTTP DELETE request.
-
core-api-downloadDownload files from Core server.
-
core-api-file-attachment-deleteDelete a file attachment from an incident — specifically from the incident’s file attachments.
-
core-api-file-checkCheck if the file exists in Cortex XSOAR (Context) by entry_id.
-
core-api-file-deleteDelete a war room (investigation) file entry.
-
core-api-file-uploadUpload to the incident a file that the user provided according to the entry_id or the content of the file.
-
core-api-getsend HTTP GET requests.
-
core-api-install-packsUpload packs to the core server from the URL or marketplace.
-
core-api-multipartSend HTTP Multipart request to upload files to Core server.
-
core-api-postsend HTTP POST request.
-
core-api-putsend HTTP PUT request.
-
core-delete-incidentsDelete Core incidents.
-
demisto-api-deleteDeprecatedDeprecated. Use core-api-delete instead.
-
demisto-api-downloadDeprecatedDeprecated. Use core-api-download instead.
-
demisto-api-getDeprecatedDeprecated. Use core-api-get instead.
-
demisto-api-install-packsDeprecatedDeprecated. Use core-api-install-packs instead.
-
demisto-api-multipartDeprecatedDeprecated. Use core-api-multipart instead.
-
demisto-api-postDeprecatedDeprecated. Use core-api-post instead.
-
demisto-api-putDeprecatedDeprecated. Use core-api-put instead.
-
demisto-delete-incidentsDeprecatedDeprecated. Use core-delete-incidents instead.
const MIN_HOSTED_XSOAR_VERSION = '8.0.0'; const PLAYBOOK_METADATA = 'playbook_metadata'; const INTEGRATION_NAME = 'CoreRESTAPI'; const xsoar_hosted = ['xsoar', 'xsoar_hosted'] const platform_hosted = ['x2', 'unified_platform'] // Default timeout for HTTP requests (3 minutes in milliseconds) const default_timeout = 3 * 60 * 1000; var serverURL = params.url; if (serverURL.slice(-1) === '/') { serverURL = serverURL.slice(0,-1); } // returns true if the current platform is XSIAM or XSOAR 8.0 and above. isHosted = function () { res = getDemistoVersion(); platform = res.platform; if ((xsoar_hosted.includes(platform) && isDemistoVersionGE(MIN_HOSTED_XSOAR_VERSION)) || platform_hosted.includes(platform)) { return true } return false } var marketplace_url = params.marketplace_url? params.marketplace_url : 'https://marketplace.xsoar.paloaltonetworks.com/content/packs/' getTenantAccountName = function () { // example: for 'https://account-testing-ysdkvou:443/acc_Test' will return 'acc_Test' const urls = demistoUrls() const server_url = urls['server'].toString() // server_url example - https://account-testing-ysdkvou:443/acc_Test var account_name = '' // check if server_url contains "/acc_" string if (server_url.indexOf("/acc_") >= 0){ const words = server_url.split('acc_') const tenant_name = words[words.length - 1] if (tenant_name !== "") { account_name = 'acc_' + tenant_name } } else{ logDebug('getTenantAccountName: The server url ' + server_url + ' does not contain the expected tenant prefix acc_'); } return account_name } getStandardAuthMethodHeaders = function(key, auth_id, content_type) { return { 'Authorization': [key], 'x-xdr-auth-id': [auth_id], 'Content-Type': [content_type], 'Accept': ['application/json'] } } getAdvancedAuthMethodHeaders = function(key, auth_id, content_type,) { const nonce = Array.from({length: 64}, () => Math.random().toString(36).charAt(2)).join(""); const timestamp = Date.now().toString(); var auth_key = key + nonce + timestamp auth_key = unescape(encodeURIComponent(auth_key)); const auth_key_hash = SHA256_hash(auth_key) return { 'x-xdr-timestamp': [timestamp], 'x-xdr-nonce': [nonce], 'x-xdr-auth-id': [auth_id], 'Authorization': [auth_key_hash], 'Content-Type': [content_type], 'Accept': ['application/json'] } } getRequestURL = function (uri) { var requestUrl = serverURL; // only when using XSIAM or XSOAR >= 8.0 we will add the /xsoar suffix // and only when it is not a /public_api or /platform endpoint. if (isHosted()) { const isPublicApi = uri.startsWith('/public_api'); const isPlatformApi = uri.startsWith('/platform'); const isXsoarApi = serverURL.endsWith('/xsoar'); if (!isXsoarApi && !isPublicApi && !isPlatformApi) { requestUrl += '/xsoar'; } } if (params.use_tenant){ requestUrl += '/' + getTenantAccountName(); } if (uri.slice(0, 1) !== '/') { requestUrl += '/'; } requestUrl += uri; return requestUrl; } sendMultipart = function (uri, entryID, body, timeoutInMilliseconds) { var requestUrl = getRequestURL(uri) try { body = JSON.parse(body); } catch (ex) { // do nothing, use the body as is in the request. logDebug('could not parse body as a JSON object, passing as is. body: ' + JSON.stringify(body)); } var key = params.apikey? params.apikey : (params.creds_apikey? params.creds_apikey.password : ''); if (key == ''){ throw 'API Key must be provided.'; } var auth_id = params.auth_id? params.auth_id : (params.creds_apikey? params.creds_apikey.identifier : ''); var headers = {} // in case the integration was installed before auth_method was added, the auth_method param will be empty so // we will use the standard auth method if (!params.auth_method || params.auth_method == 'Standard'){ headers = getStandardAuthMethodHeaders(key, auth_id, 'multipart/form-data') } else if (params.auth_method == 'Advanced') { headers = getAdvancedAuthMethodHeaders(key, auth_id, 'multipart/form-data') } // Default timeout to 3 minutes if not provided timeoutInMilliseconds = timeoutInMilliseconds ? timeoutInMilliseconds : 3 * 60 * 1000; // timeout in milliseconds var res; var tries = 0; do { logDebug('Calling httpMultipart from sendMultipart, try number ' + tries + ', with requestUrl = ' + requestUrl + ', entryID = ' + entryID + ', body = ' + JSON.stringify(body) + ', insecure = ' + params.insecure + ', proxy = ' + params.proxy + ', undefined = ' + undefined + ', file, ' + ' timeout in milliseconds = ' + timeoutInMilliseconds); res = httpMultipart( requestUrl, entryID, { Headers: headers, }, body, params.insecure, params.proxy, undefined, 'file', undefined, undefined, timeoutInMilliseconds ); logDebug('The result of calling httpMultipart, with the requestUrl = ' + requestUrl + ' is ' + res.Status + ' and res is ' + JSON.stringify(res)) tries++; } while (tries < 3 && res.Status.startsWith('timeout')); logDebug("Ran httpMultipart() " + tries + " time(s)") if (res.StatusCode < 200 || res.StatusCode >= 300) { logDebug('httpMultipart request to requestUrl = ' + requestUrl + ' failed.\nStatus code: ' + res.StatusCode + '.\nBody: ' + JSON.stringify(res) + '.'); throw 'Core REST APIs - Request to requestUrl = ' + requestUrl + ' Failed.\nStatus code: ' + res.StatusCode + '.\nBody: ' + JSON.stringify(res) + '.'; } logDebug('httpMultipart request to requestUrl = ' + requestUrl + ' was successful.'); try { var response = res.Body; try { response = JSON.parse(res.Body); } catch (ex) { // do nothing, already handled prior the try/catch } return {response: response}; } catch (ex) { throw 'Core REST APIs - Error parsing response in httpMultipart request - ' + ex + '\nBody:' + res.Body; } }; var addPlaybookMetadataToRequest = function(body, command) { try { var requestBodyObject = JSON.parse(body); var playbookTaskInfoJson = JSON.parse(playbookTaskInfo); requestBodyObject.request_data.playbook_metadata = { 'playbook_id': playbookTaskInfoJson.playbookID, 'playbook_name': playbookTaskInfoJson.playbookName, 'task_id': playbookTaskInfoJson.taskID, 'task_name': playbookTaskInfoJson.taskName, 'integration_name': INTEGRATION_NAME, 'command_name': command, } logDebug("Added playbook-metadata to request body " + requestBodyObject.request_data.playbook_metadata); } catch(error) { logError("Error parsing as a JSON object playbookTaskInfo: " + error); } finally { body = JSON.stringify(requestBodyObject); } return body; }; var sendRequest = function(method, uri, body, raw, timeout = default_timeout) { var requestUrl = getRequestURL(uri); var key = params.apikey ? params.apikey : (params.creds_apikey ? params.creds_apikey.password : ''); if (key == '') { throw 'API Key must be provided.'; } var auth_id = params.auth_id ? params.auth_id : (params.creds_apikey ? params.creds_apikey.identifier : ''); var headers = {}; if (!params.auth_method || params.auth_method == 'Standard') { headers = getStandardAuthMethodHeaders(key, auth_id, 'application/json'); } else if (params.auth_method == 'Advanced') { if (!auth_id) { throw 'Core REST APIs - please choose "Standard Authentication method" or provide the API Key ID.'; } headers = getAdvancedAuthMethodHeaders(key, auth_id, 'application/json'); } if (requestUrl.includes("start_xql_query") && method === 'POST') { body = addPlaybookMetadataToRequest(body, command); } var res; var tries = 0; var maxTries = 3; do { logDebug('Calling http() from sendRequest, try number ' + tries); res = http( requestUrl, { Method: method, Headers: headers, Body: body, SaveToFile: raw }, params.insecure, params.proxy, undefined, undefined, timeout ); logDebug( 'Result of http() requestUrl = ' + requestUrl + ' status = ' + res.Status); tries++; } while (tries < maxTries && res.Status && res.Status.startsWith('timeout')); logDebug("Ran http() " + tries + " time(s)"); if (res.StatusCode < 200 || res.StatusCode >= 300) { logDebug('http() request failed.\nStatus code: ' + res.StatusCode + '.\nBody: ' + JSON.stringify(res)); throw 'Core REST APIs - Request to requestUrl = ' + requestUrl + ' Failed.\nStatus code: ' + res.StatusCode + '.\nBody: ' + JSON.stringify(res); } logDebug('http() request was successful.'); if (raw) { return res; } try { var response = res.Body; try { response = JSON.parse(res.Body); } catch (ex) { // keep raw body if not JSON } return { response: response }; } catch (ex) { throw 'Core REST APIs - Error parsing response - http() request to requestUrl = ' + requestUrl + '\nError: ' + ex + '\nBody:' + res.Body; } }; function reduce_data(data, keep_fields) { var new_d = {}; for (var field_index = 0; field_index < keep_fields.length; field_index += 1) { var field = keep_fields[field_index]; if (field in data) { new_d[field] = data[field]; } } return new_d; } var deleteIncidents = function(ids_to_delete) { var body = { ids: ids_to_delete, all: false, filter: {"size": 1}, excludeIncidentsResponseData: true // exclude unrelated data in response }; var res = sendRequest('POST', '/incident/batchDelete', JSON.stringify(body)); if (isError(res[0])) { throw res[0].Contents; } var relevant_headers = ['totalDeleted', "notUpdated", 'total'] var response = reduce_data(res['response'], relevant_headers) var md = tableToMarkdown('Core delete incidents', response); return { ContentsFormat: formats.json, Type: entryTypes.note, Contents: {"response": response}, HumanReadable: md }; }; var installPack = function(pack_url, entry_id, skip_verify, skip_validation, timeoutInSeconds){ let file_path; // Convert timeout from seconds to milliseconds, default to 180 seconds (3 minutes) var timeoutInMilliseconds = timeoutInSeconds ? parseInt(timeoutInSeconds) * 1000 : 3 * 60 * 1000; if (entry_id){ file_path = entry_id; } else{ var method = 'GET'; var save_to_file = true; // download pack zip file logDebug('Calling http() from installPack, with pack_url = ' + pack_url + ', Method = ' + method + ', SaveToFile = ' + save_to_file + ', timeout in milliseconds = ' + timeoutInMilliseconds); var res = http( pack_url, { Method: method, Headers: {}, SaveToFile: save_to_file }, undefined, undefined, undefined, undefined, timeoutInMilliseconds ); if (res.StatusCode < 200 || res.StatusCode >= 300) { throw 'Core REST APIs - Failed to download pack file from ' + pack_url; } file_path = res.Path; logDebug('The result of http() from installPack, to pack_url = ' + pack_url + ' is ' + res.StatusCode) } let upload_url = 'contentpacks/installed/upload?' // set the skipVerify parameter if(isDemistoVersionGE('6.5.0')){ if (skip_verify && skip_verify === 'false') { upload_url+='skipVerify=false' }else{ upload_url+='skipVerify=true' } } // set the skipValidation parameter if(isDemistoVersionGE('6.6.0')){ if (skip_validation && skip_validation === 'false') { upload_url+='&skipValidation=false' }else{ upload_url+='&skipValidation=true' } } // upload the pack sendMultipart(upload_url, file_path,'{}', timeoutInMilliseconds); }; var installPacks = function(packs_to_install, file_url, entry_id, skip_verify, skip_validation, timeoutInSeconds = 3 * 60) { if ((!packs_to_install) && (!file_url) && (!entry_id)) { throw 'Either packs_to_install, file_url or entry_id argument must be provided.'; } else if (file_url) { installPack(file_url, undefined, skip_verify, skip_validation, timeoutInSeconds) logDebug('Pack installed successfully from ' + file_url) return 'The pack installed successfully from the file ' + file_url } else if (entry_id) { installPack(undefined, entry_id, skip_verify, skip_validation, timeoutInSeconds) logDebug('The pack installed successfully from the file.') return 'The pack installed successfully from the file.' } else{ let installed_packs = [] let packs = JSON.parse(packs_to_install); for (let pack_index = 0; pack_index < packs.length; pack_index += 1) { let pack = packs[pack_index]; let pack_id = Object.keys(pack)[0] let pack_version = pack[pack_id] let pack_url = '{0}{1}/{2}/{3}.zip'.format(marketplace_url,pack_id,pack_version,pack_id) installPack(pack_url, undefined, skip_verify, skip_validation, timeoutInSeconds) logDebug(pack_id + ' pack installed successfully') installed_packs.push(pack_id) } if (installed_packs.length === 0) { return 'No pack has been installed, please check that the pack name and version are correct.' } else { return 'The following packs installed successfully: ' + installed_packs.join(", ") } } }; /* helper functions */ /** * deletes an entry by entryID by the key_to_delete Arguments: @param {String} incident_id -- the incident id @param {String} entry_id -- the entry ID of the file Returns: CommandResults """ */ var uploadFile= function(incident_id, entry_id) { timeout = 3 * 60 * 1000; // timeout in milliseconds logDebug('Calling httpMultipart from uploadFile, with the url /entry/upload/' + incident_id + ' and entry_id = ' + entry_id + ', timeout in milliseconds = ' + timeout); var res = httpMultipart(`/entry/upload/${incident_id}`, entry_id, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, timeout); logDebug('After Calling to httpMultipart with the url /entry/upload/' + incident_id + ' and entry_id = ' + entry_id + '. The satus code: ' + res.StatusCode); if (isError(res[0])) { throw res[0].Contents; } return res; }; /** * deletes a file by entryID Arguments: @param {String} delete_artifact -- in order to delete the artifact @param {String} entry_id -- entry ID of the file Returns: CommandResults """ */ var deleteFileRequest = function (entry_id, delete_artifact = true) { const body_content = JSON.stringify({ id: entry_id, deleteArtifact: delete_artifact}); return sendRequest( 'POST', '/entry/delete/v2', body_content); }; /** * Sends http request to delete attachment Arguments: @param {String} incident_id -- incident id to upload the file to @param {String} file_path -- the file path to delete @param {String} field_name -- Name of the field (type attachment) you want to remove the attachment Returns: Results """ */ var deleteAttachmentRequest=function(incident_id, attachment_path, field_name = 'attachment') { body = JSON.stringify({ fieldName: field_name, files: { [attachment_path]: { path: attachment_path } }, originalAttachments: [ { path: attachment_path } ] }); try{ return sendRequest('POST', `/incident/remove/${incident_id}`, body); } catch (e) { throw new Error(`File already deleted or not found.\n${e}`); } }; /** * Upload a new file Arguments: @param {String} incident_id -- incident id to upload the file to @param {String} file_content -- content of the file to upload @param {String} file_name -- name of the file in the dest incident @param {String} entryID -- entry ID of the file Returns: CommandResults -- Readable output Note: You can give either the entryID or file_name. """ */ var fileUploadCommand = function(incident_id, file_content, file_name, entryID ) { incident_id = (typeof incident_id === 'undefined')? investigation.id: incident_id; if (incident_id!=investigation.id){ log(`Note that the file would be uploaded to ${incident_id} from incident ${investigation.id}`); } if ((!file_name) && (!entryID)) { throw 'Either file_name or entry_id argument must be provided.'; } var fileId = ''; if ((!entryID)) { logDebug('Calling saveFile for the file ' + file_name); fileId = saveFile(file_content); logDebug('Calling uploadFile for the incident ' + incident_id + ' with fileId = ' + fileId); response = uploadFile(incident_id, fileId); logDebug('After the call to uploadFile for the incident ' + incident_id + ' with fileId = ' + fileId + '. Status code: ' + response.StatusCode); } else { if (file_name === undefined) { logDebug('Calling dq with the invContext of incident ' + incident_id + ' and the transformation string: File(val.EntryID == ${entryID}).Name'); file_name = dq(invContext, `File(val.EntryID == ${entryID}).Name`); logDebug('After calling dq. The returned file name is ' + file_name + '. The parameters were the invContext of incident ' + incident_id + ' and the transformation string: File(val.EntryID == ${entryID}).Name'); } if (Array.isArray(file_name)) { if (file_name.length > 0) { file_name = file_name[0]; } else { file_name = undefined; } } response_multi= sendMultipart(`/incident/upload/${incident_id}`,entryID,'{}'); return `The file ${entryID} uploaded successfully to incident ${incident_id}. `; } var md = `File ${file_name} uploaded successfully to incident ${incident_id}.`; fileId = file_name ? fileId : entryID; return { Type: entryTypes.file, FileID: fileId, File: file_name, Contents: file_content, HumanReadable: md }; }; /** * Deletes a specific file. Arguments: @param {String} entryId -- entry ID of the file Returns: Message that the file was deleted successfully + entry_id """ */ // getting the context data var fileDeleteCommand = function(EntryID) { files = invContext['File']; if (!files){ throw new Error(`Files not found.`); } files = (invContext['File'] instanceof Array)? invContext['File']:[invContext['File']]; if (files[0]=='undefined'){ throw new Error(`Files not found.`); } var not_found = true for (var i = 0 ;i <=Object.keys(files).length - 1; i++) { if (files[i]['EntryID'] == EntryID) { not_found= false } } if(not_found){ throw new Error(`File already deleted or not found.`); } deleteFileRequest(EntryID); return {Type: entryTypes.note, Contents: '', ContentsType: formats.json, HumanReadable: `File ${EntryID} was deleted successfully.`} } /** This command checks if the file is existing. Arguments: @param {String} EntryID -- entry ID of the file Returns: Dictionary with EntryID as key and boolean if the file exists as value. */ function coreApiFileCheckCommand(EntryID) { files = invContext['File']instanceof Array? invContext['File']:[invContext['File']]; var file_found = false; var human_readable = `File ${EntryID} does not exist`; if (typeof files['0'] !== 'undefined') { for (var i = 0 ;i <=Object.keys(files).length - 1; i++) { if (files[i]['EntryID'] == EntryID) { file_found= true ; human_readable = `File ${EntryID} exists`; } } } return { Type: entryTypes.note, Contents: {[EntryID]:file_found}, HumanReadable: human_readable, EntryContext: {[`IsFileExists(val.${EntryID}==${EntryID})`]:{[EntryID]:file_found}} }; }; /** This command deletes attachment from an incident. Arguments: @param {String} incident_id -- incident id to delete the file from @param {String} attachment_path -- the file path @param {String} field_name -- Name of the field (type attachment) you want to remove the attachment Returns: Show a message that the file was deleted successfully */ var fileDeleteAttachmentCommand = function (attachment_path, incident_id, field_name){ incident_id = (typeof incident_id == 'undefined')? investigation.id: incident_id; deleteAttachmentRequest(incident_id, attachment_path, field_name); return `Attachment ${attachment_path} deleted `; }; switch (command) { case 'test-module': res = sendRequest('GET','user'); // throws an exception if the request fails return 'ok'; case 'demisto-api-post': case 'core-api-post': if(args.body) var body = JSON.parse(args.body); else logDebug('The body is empty.'); var timeout; // Declare timeout. if (args.timeout) { var parsedTimeout = parseInt(args.timeout); if (!isNaN(parsedTimeout) && parsedTimeout >= 0) { timeout = parsedTimeout * 60 * 1000; // timeout in milliseconds logDebug('Timeout was set to ' + timeout + ' milliseconds.'); } } if (!timeout) { timeout = default_timeout; // Default 3 minutes timeout logDebug('Timeout was not provided or it is invalid. Will use the default 3 minutes timeout.'); } return sendRequest('POST', args.uri, args.body, false, timeout); case 'demisto-api-get': case 'core-api-get': return sendRequest('GET',args.uri); case 'demisto-api-put': case 'core-api-put': var body = JSON.parse(args.body); return sendRequest('PUT',args.uri, args.body); case 'demisto-api-delete': case 'core-api-delete': return sendRequest('DELETE',args.uri); case 'demisto-api-multipart': case 'core-api-multipart': return sendMultipart(args.uri, args.entryID, args.body); case 'demisto-api-download': case 'core-api-download': var res = sendRequest('GET',args.uri,args.body,true); var filename = res.Path; if (args.filename) { filename = args.filename; } else { var disposition = res.Headers['Content-Disposition'][0].split('='); if (disposition.length === 2) { filename = disposition[1]; } } var desc = args.description || ''; return ({Type: entryTypes.file, FileID: res.Path, File: filename, Contents: desc}); case 'demisto-delete-incidents': case 'core-delete-incidents': var ids = argToList(args.ids); return deleteIncidents(ids); case 'demisto-api-install-packs': case 'core-api-install-packs': return installPacks(args.packs_to_install, args.file_url, args.entry_id, args.skip_verify, args.skip_validation, args.timeout_in_seconds); case 'core-api-file-upload': return fileUploadCommand(args.incident_id, args.file_content, args.file_name, args.entry_id) case 'core-api-file-delete': return fileDeleteCommand(args.entry_id); case 'core-api-file-attachment-delete': return fileDeleteAttachmentCommand(args.file_path, args.incident_id, args.field_name); case 'core-api-file-check': return coreApiFileCheckCommand(args.entry_id); default: throw 'Core REST APIs - unknown command'; }