New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
XSOAR NG CoreRestAPI support #23804
XSOAR NG CoreRestAPI support #23804
Changes from 10 commits
077a34c
7c7a6d8
2da5e90
bc89da7
475f8bc
81e1fcd
a86e49e
664bcb3
aeca4de
842582e
9316e9a
284c1a0
ddf0be0
de4b010
9f459f8
c4571e9
db72a93
16e3186
357c620
cd3a1fb
8c893e5
b8ddd3a
8b3f829
b534504
886491a
9e564de
a249e15
062f8b2
edb9994
4451e23
7b1c731
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,33 @@ if (serverURL.slice(-1) === '/') { | |
serverURL = serverURL.slice(0,-1); | ||
} | ||
serverURL = serverURL + '/xsoar' | ||
var marketplace_url = params.marketplace_url? params.marketplace_url : 'https://storage.googleapis.com/marketplace-dist/content/packs/' | ||
|
||
getStandardAuthMethodHeaders = function(key, auth_id) { | ||
return { | ||
'Authorization': [key], | ||
'x-xdr-auth-id': [auth_id], | ||
'Content-Type': ['multipart/form-data'], | ||
'Accept': ['application/json'] | ||
} | ||
} | ||
|
||
getAdvancedAuthMethodHeaders = function(key, auth_id) { | ||
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': ['multipart/form-data'], | ||
'Accept': ['application/json'] | ||
} | ||
} | ||
|
||
sendMultipart = function (uri, entryID, body) { | ||
var requestUrl = serverURL; | ||
|
@@ -24,16 +51,18 @@ sendMultipart = function (uri, entryID, body) { | |
if (auth_id == ''){ | ||
throw 'Auth ID must be provided.'; | ||
} | ||
var headers = {} | ||
if (params.auth_method == 'standard'){ | ||
dansterenson marked this conversation as resolved.
Show resolved
Hide resolved
|
||
headers = getStandardAuthMethodHeaders(key, auth_id) | ||
} | ||
else if (params.auth_method == 'advanced') { | ||
headers = getAdvancedAuthMethodHeaders(key, auth_id) | ||
} | ||
var res = httpMultipart( | ||
requestUrl, | ||
entryID, | ||
{ | ||
Headers: { | ||
'Authorization': key, | ||
'x-xdr-auth-id': auth_id, | ||
'Content-Type': ['multipart/form-data'], | ||
'Accept': ['application/json'] | ||
}, | ||
Headers: headers, | ||
}, | ||
body, | ||
params.insecure, | ||
|
@@ -64,24 +93,26 @@ var sendRequest = function(method, uri, body, raw) { | |
requestUrl += '/'; | ||
} | ||
requestUrl += uri; | ||
var key = [params.apikey? params.apikey : (params.creds_apikey? params.creds_apikey.password : '')]; | ||
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 auth_id = params.auth_id? params.auth_id : (params.creds_apikey? params.creds_apikey.identifier : ''); | ||
if (auth_id == ''){ | ||
throw 'Auth ID must be provided.'; | ||
} | ||
var headers = {} | ||
if (params.auth_method == 'standard'){ | ||
headers = getStandardAuthMethodHeaders(key, auth_id) | ||
} | ||
else if (params.auth_method == 'advanced') { | ||
headers = getAdvancedAuthMethodHeaders(key, auth_id) | ||
} | ||
var res = http( | ||
requestUrl, | ||
{ | ||
Method: method, | ||
Headers: { | ||
'Accept': ['application/json'], | ||
'content-type': ['application/json'], | ||
'authorization': key, | ||
'x-xdr-auth-id': auth_id | ||
}, | ||
Headers: headers, | ||
Body: body, | ||
SaveToFile: raw | ||
}, | ||
|
@@ -109,7 +140,35 @@ var sendRequest = function(method, uri, body, raw) { | |
} | ||
}; | ||
|
||
var deleteIncidents = function(ids_to_delete) { | ||
function reduce_one_entry(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 (data[field]) { | ||
new_d[field] = data[field]; | ||
} | ||
} | ||
return new_d; | ||
} | ||
|
||
function reduce_data(data, fields_to_keep) { | ||
if (data instanceof Array) { | ||
var new_data = []; | ||
for (var data_index = 0; data_index < data.length; data_index += 1) { | ||
var d = data[data_index]; | ||
new_data.push(reduce_one_entry(d, fields_to_keep)); | ||
} | ||
return new_data; | ||
} | ||
else { | ||
if (data.constructor == Object) { | ||
return [reduce_one_entry(data, fields_to_keep)]; | ||
} | ||
} | ||
return data; | ||
} | ||
|
||
var deleteIncidents = function(ids_to_delete, fields_to_keep) { | ||
Comment on lines
-112
to
+197
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was taken from DemistoRestAPI integration. |
||
var body = { | ||
ids: ids_to_delete, | ||
all: false, | ||
|
@@ -121,7 +180,10 @@ var deleteIncidents = function(ids_to_delete) { | |
throw res[0].Contents; | ||
} | ||
|
||
var response = res['response'] | ||
var response = res['response']; | ||
if (fields_to_keep && (fields_to_keep != "all")) { | ||
response['data'] = reduce_data(response['data'], fields_to_keep); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was taken from DemistoRestAPI integration. |
||
var md = tableToMarkdown('Demisto delete incidents', response, ['data', 'total', "notUpdated"]); | ||
|
||
return { | ||
|
@@ -132,6 +194,83 @@ var deleteIncidents = function(ids_to_delete) { | |
}; | ||
}; | ||
|
||
var installPack = function(pack_url, entry_id, skip_verify, skip_validation){ | ||
let file_path; | ||
if (entry_id){ | ||
file_path = entry_id; | ||
} | ||
else{ | ||
// download pack zip file | ||
var res = http( | ||
pack_url, | ||
{ | ||
Method: 'GET', | ||
Headers: {}, | ||
SaveToFile: true | ||
}); | ||
|
||
if (res.StatusCode < 200 || res.StatusCode >= 300) { | ||
throw 'Demisto REST APIs - Failed to download pack file from ' + pack_url; | ||
} | ||
file_path = res.Path; | ||
} | ||
|
||
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,'{}'); | ||
}; | ||
|
||
var installPacks = function(packs_to_install, file_url, entry_id, skip_verify, skip_validation) { | ||
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) | ||
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) | ||
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) | ||
logDebug(pack_id + ' pack installed successfully') | ||
installed_packs.push(pack_id) | ||
} | ||
|
||
return 'The following packs installed successfully: ' + installed_packs.join(", ") | ||
} | ||
}; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was taken from DemistoRestAPI integration. |
||
switch (command) { | ||
case 'test-module': | ||
sendRequest('GET','user'); | ||
|
@@ -174,7 +313,10 @@ switch (command) { | |
case 'demisto-delete-incidents': | ||
case 'core-delete-incidents': | ||
var ids = argToList(args.ids); | ||
return deleteIncidents(ids); | ||
var fields = argToList(args.fields); | ||
return deleteIncidents(ids, fields); | ||
case 'demisto-api-install-packs': | ||
return installPacks(args.packs_to_install, args.file_url, args.entry_id, args.skip_verify, args.skip_validation); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was taken from DemistoRestAPI integration. |
||
default: | ||
throw 'Core REST APIs - unknown command'; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,20 @@ configuration: | |
name: creds_apikey | ||
type: 9 | ||
required: false | ||
- display: Authentication Method | ||
name: auth_method | ||
type: 15 | ||
required: false | ||
defaultvalue: advanced | ||
additionalinfo: Whether authentication should be using standard API key or advanced API key. | ||
options: | ||
- standard | ||
- advanced | ||
- display: Base marketplace url | ||
name: marketplace_url | ||
defaultvalue: https://storage.googleapis.com/marketplace-dist/content/packs/ | ||
type: 0 | ||
required: false | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was taken from DemistoRestAPI integration. |
||
- display: Trust any certificate (not secure) | ||
name: insecure | ||
type: 8 | ||
|
@@ -23,6 +37,11 @@ configuration: | |
name: proxy | ||
type: 8 | ||
required: false | ||
- display: Use tenant | ||
additionalinfo: Whether API calls should be made to the current tenant instead of the master tenant. | ||
dansterenson marked this conversation as resolved.
Show resolved
Hide resolved
|
||
name: use_tenant | ||
type: 8 | ||
required: false | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be relevant to XSIAM and NG in the future. |
||
script: | ||
script: '' | ||
type: javascript | ||
|
@@ -89,8 +108,47 @@ script: | |
required: true | ||
description: IDs of the incidents to delete | ||
isArray: true | ||
- name: fields | ||
description: 'Comma separated list of fields to return, case sensitive. Set | ||
"all" for all fields. WARNING: Setting all fields may result in big results.' | ||
required: false | ||
isArray: true | ||
defaultValue: id,name,type,severity,status | ||
description: Delete Demisto incidents | ||
execution: true | ||
- name: demisto-api-install-packs | ||
arguments: | ||
- name: packs_to_install | ||
required: false | ||
description: 'The packs to install in JSON format (e.g. [{"AutoFocus": "2.0.8"}] ).' | ||
isArray: true | ||
- name: file_url | ||
description: 'The pack zip file url.' | ||
required: false | ||
isArray: false | ||
- name: entry_id | ||
description: 'The War Room entry ID of the pack zip file.' | ||
required: false | ||
isArray: false | ||
- name: skip_verify | ||
description: 'If true will skip pack signature validation, Available from 6.5.0 server version.' | ||
required: false | ||
isArray: false | ||
defaultValue: 'true' | ||
auto: PREDEFINED | ||
predefined: | ||
- 'true' | ||
- 'false' | ||
- name: skip_validation | ||
description: 'If true will skip all pack validations, Available from 6.6.0 server version.' | ||
required: false | ||
isArray: false | ||
defaultValue: 'true' | ||
auto: PREDEFINED | ||
predefined: | ||
- 'true' | ||
- 'false' | ||
description: Upload packs to Demisto server from url or the marketplace. | ||
- name: core-api-post | ||
arguments: | ||
- name: uri | ||
|
@@ -155,9 +213,41 @@ script: | |
isArray: true | ||
description: Delete Demisto incidents | ||
execution: true | ||
- name: core-api-install-packs | ||
arguments: | ||
- name: packs_to_install | ||
required: false | ||
description: 'The packs to install in JSON format (e.g. [{"AutoFocus": "2.0.8"}] ).' | ||
isArray: true | ||
- name: file_url | ||
description: 'The pack zip file url.' | ||
required: false | ||
isArray: false | ||
- name: entry_id | ||
description: 'The War Room entry ID of the pack zip file.' | ||
required: false | ||
isArray: false | ||
- name: skip_verify | ||
description: 'If true will skip pack signature validation, Available from 6.5.0 server version.' | ||
required: false | ||
isArray: false | ||
defaultValue: 'true' | ||
auto: PREDEFINED | ||
predefined: | ||
- 'true' | ||
- 'false' | ||
- name: skip_validation | ||
description: 'If true will skip all pack validations, Available from 6.6.0 server version.' | ||
required: false | ||
isArray: false | ||
defaultValue: 'true' | ||
auto: PREDEFINED | ||
predefined: | ||
- 'true' | ||
- 'false' | ||
description: Upload packs to Demisto server from url or the marketplace. | ||
runonce: false | ||
tests: | ||
- No tests | ||
marketplaces: | ||
- marketplacev2 | ||
fromversion: 5.0.0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
Creating API keys is done in the Cortex XSIAM interface, under Settings -> Configurations -> API Keys | ||
Creating API keys is done in the Cortex XSIAM interface, under Settings -> Configurations -> API Keys | ||
dansterenson marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Creating API keys is done in the Cortex XSOAR interface, under Settings -> Integrations -> API Keys |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this url should differ if the integration running in XSIAM or XSOAR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no way to distinguish between XSIAM and XSOAR. It should be added manually by the customer.