Skip to content
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

Merged
merged 31 commits into from Jan 19, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
077a34c
fix
dansterenson Jan 4, 2023
7c7a6d8
Merge branch 'master' into XSOAR-NG-update-Demisto-Rest-API
dansterenson Jan 8, 2023
2da5e90
yml fixes
dansterenson Jan 8, 2023
bc89da7
more fixes
dansterenson Jan 9, 2023
475f8bc
Merge branch 'master' into XSOAR-NG-update-Demisto-Rest-API
dansterenson Jan 11, 2023
81e1fcd
Merge branch 'master' into XSOAR-NG-update-Demisto-Rest-API
dansterenson Jan 12, 2023
a86e49e
add support to Standard and Advanced
dansterenson Jan 12, 2023
664bcb3
fix readme and yml
dansterenson Jan 15, 2023
aeca4de
Merge branch 'master' into XSOAR-NG-update-Demisto-Rest-API
dansterenson Jan 15, 2023
842582e
update RN
dansterenson Jan 15, 2023
9316e9a
Update Packs/DemistoRESTAPI/Integrations/CoreRESTAPI/CoreRESTAPI.yml
dansterenson Jan 15, 2023
284c1a0
support empty auth_method
dansterenson Jan 15, 2023
ddf0be0
Merge branch 'XSOAR-NG-update-Demisto-Rest-API' of github.com:demisto…
dansterenson Jan 15, 2023
de4b010
remove marketplaces field
dansterenson Jan 15, 2023
9f459f8
auth ID handle and deprecate DemistoRestApi
dansterenson Jan 17, 2023
c4571e9
Merge branch 'master' into XSOAR-NG-update-Demisto-Rest-API
dansterenson Jan 17, 2023
db72a93
update RN
dansterenson Jan 17, 2023
16e3186
fix validation errors
dansterenson Jan 17, 2023
357c620
remove additional info
dansterenson Jan 17, 2023
cd3a1fb
Merge branch 'master' into XSOAR-NG-update-Demisto-Rest-API
dansterenson Jan 17, 2023
8c893e5
more fixes
dansterenson Jan 18, 2023
b8ddd3a
Merge branch 'master' into XSOAR-NG-update-Demisto-Rest-API
dansterenson Jan 18, 2023
8b3f829
more fixes
dansterenson Jan 18, 2023
b534504
Add core-api-install-packs
dansterenson Jan 19, 2023
886491a
Fix names
dansterenson Jan 19, 2023
9e564de
Merge branch 'master' into XSOAR-NG-update-Demisto-Rest-API
dansterenson Jan 19, 2023
a249e15
deprecate in description
dansterenson Jan 19, 2023
062f8b2
deprecate in description
dansterenson Jan 19, 2023
edb9994
update RN
dansterenson Jan 19, 2023
4451e23
more fixes
dansterenson Jan 19, 2023
7b1c731
Merge branch 'master' into XSOAR-NG-update-Demisto-Rest-API
dansterenson Jan 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
176 changes: 159 additions & 17 deletions Packs/DemistoRESTAPI/Integrations/CoreRESTAPI/CoreRESTAPI.js
Expand Up @@ -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/'
Copy link
Contributor

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

Copy link
Contributor Author

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.


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;
Expand All @@ -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,
Expand Down Expand Up @@ -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
},
Expand Down Expand Up @@ -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
Copy link
Contributor Author

Choose a reason for hiding this comment

The 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,
Expand All @@ -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);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 {
Expand All @@ -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(", ")
}
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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');
Expand Down Expand Up @@ -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);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was taken from DemistoRestAPI integration.

default:
throw 'Core REST APIs - unknown command';
}
92 changes: 91 additions & 1 deletion Packs/DemistoRESTAPI/Integrations/CoreRESTAPI/CoreRESTAPI.yml
Expand Up @@ -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
Copy link
Contributor Author

Choose a reason for hiding this comment

The 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
Expand All @@ -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
Copy link
Contributor Author

Choose a reason for hiding this comment

The 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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
@@ -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