From 351694b25ffa1121e80fe3094083de843ff18046 Mon Sep 17 00:00:00 2001 From: content-bot <55035720+content-bot@users.noreply.github.com> Date: Thu, 19 Sep 2024 10:45:14 +0300 Subject: [PATCH] Add sekoia xdr pack without mirroring (#36252) (#36339) * Add sekoia xdr pack without mirroring * Change docker version * Delete some yml configurations * Change yaml files * Apply linter Co-authored-by: TOUFIKI Zakarya <57439240+TOUFIKIzakarya@users.noreply.github.com> --- Packs/SekoiaXDR/.pack-ignore | 0 Packs/SekoiaXDR/.secrets-ignore | 5 + Packs/SekoiaXDR/Author_image.png | Bin 0 -> 2711 bytes .../classifier-Sekoia_XDR_-_Classifier.json | 23 + ...assifier-Sekoia_XDR_-_Incoming_Mapper.json | 126 ++ ...ncident_sekoia_xdr_alertdetails_field.json | 31 + ...incident_sekoia_xdr_alertreject_field.json | 31 + ...incident_sekoia_xdr_alertstatus_field.json | 31 + .../incident_sekoia_xdr_firstseen_field.json | 31 + .../incident_sekoia_xdr_killchain_field.json | 62 + .../Sekoia_XDR_Incident_Types.json | 56 + .../Integrations/SekoiaXDR/README.md | 779 ++++++++ .../Integrations/SekoiaXDR/SekoiaXDR.py | 1248 +++++++++++++ .../Integrations/SekoiaXDR/SekoiaXDR.yml | 1122 +++++++++++ .../SekoiaXDR/SekoiaXDR_description.md | 32 + .../SekoiaXDR/SekoiaXDR_image.png | Bin 0 -> 2711 bytes .../Integrations/SekoiaXDR/SekoiaXDR_test.py | 549 ++++++ .../SekoiaXDR/command_example.txt | 19 + .../test_data/SekoiaXDR_get_alert.json | 356 ++++ .../test_data/SekoiaXDR_get_alert_cases.json | 27 + .../SekoiaXDR_get_alert_comments.json | 32 + .../SekoiaXDR_get_alert_workflow.json | 24 + .../test_data/SekoiaXDR_get_alerts.json | 120 ++ .../test_data/SekoiaXDR_get_asset.json | 39 + .../test_data/SekoiaXDR_get_assets.json | 88 + .../test_data/SekoiaXDR_get_killchain.json | 8 + .../SekoiaXDR_get_killchain_mirroring.json | 8 + .../test_data/SekoiaXDR_get_user.json | 22 + .../test_data/SekoiaXDR_list_assets.json | 47 + .../SekoiaXDR_post_alert_comment.json | 9 + .../test_data/SekoiaXDR_post_asset_attr.json | 5 + .../test_data/SekoiaXDR_post_asset_key.json | 5 + .../test_data/SekoiaXDR_query_events.json | 28 + .../SekoiaXDR_query_events_status.json | 28 + .../test_data/SekoiaXDR_retrieve_events.json | 124 ++ .../layoutscontainer-Sekoia_XDR_Layout.json | 1650 +++++++++++++++++ Packs/SekoiaXDR/README.md | 13 + .../Scripts/SekoiaXDRAddComment/README.md | 25 + .../SekoiaXDRAddComment.py | 36 + .../SekoiaXDRAddComment.yml | 26 + .../SekoiaXDRAddComment_test.py | 33 + .../Scripts/SekoiaXDRChangeStatus/README.md | 25 + .../SekoiaXDRChangeStatus.py | 31 + .../SekoiaXDRChangeStatus.yml | 30 + .../SekoiaXDRChangeStatus_test.py | 16 + .../Scripts/SekoiaXDRCloseAlert/README.md | 21 + .../SekoiaXDRCloseAlert.py | 50 + .../SekoiaXDRCloseAlert.yml | 19 + .../SekoiaXDRCloseAlert_test.py | 51 + .../Scripts/SekoiaXDRPrintAssets/README.md | 21 + .../SekoiaXDRPrintAssets.py | 50 + .../SekoiaXDRPrintAssets.yml | 19 + .../SekoiaXDRPrintAssets_test.py | 30 + .../Scripts/SekoiaXDRPrintCase/README.md | 21 + .../SekoiaXDRPrintCase/SekoiaXDRPrintCase.py | 54 + .../SekoiaXDRPrintCase/SekoiaXDRPrintCase.yml | 19 + .../SekoiaXDRPrintCase_test.py | 90 + .../Scripts/SekoiaXDRPrintComments/README.md | 21 + .../SekoiaXDRPrintComments.py | 50 + .../SekoiaXDRPrintComments.yml | 19 + .../SekoiaXDRPrintComments_test.py | 93 + Packs/SekoiaXDR/pack_metadata.json | 23 + 62 files changed, 7651 insertions(+) create mode 100644 Packs/SekoiaXDR/.pack-ignore create mode 100644 Packs/SekoiaXDR/.secrets-ignore create mode 100644 Packs/SekoiaXDR/Author_image.png create mode 100644 Packs/SekoiaXDR/Classifiers/classifier-Sekoia_XDR_-_Classifier.json create mode 100644 Packs/SekoiaXDR/Classifiers/classifier-Sekoia_XDR_-_Incoming_Mapper.json create mode 100644 Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_alertdetails_field.json create mode 100644 Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_alertreject_field.json create mode 100644 Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_alertstatus_field.json create mode 100644 Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_firstseen_field.json create mode 100644 Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_killchain_field.json create mode 100644 Packs/SekoiaXDR/IncidentTypes/Sekoia_XDR_Incident_Types.json create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/README.md create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR.py create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR.yml create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR_description.md create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR_image.png create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR_test.py create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/command_example.txt create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert.json create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_cases.json create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_comments.json create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_workflow.json create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alerts.json create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_asset.json create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_assets.json create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_killchain.json create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_killchain_mirroring.json create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_user.json create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_list_assets.json create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_alert_comment.json create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_asset_attr.json create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_asset_key.json create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_query_events.json create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_query_events_status.json create mode 100644 Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_retrieve_events.json create mode 100644 Packs/SekoiaXDR/Layouts/layoutscontainer-Sekoia_XDR_Layout.json create mode 100644 Packs/SekoiaXDR/README.md create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRAddComment/README.md create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRAddComment/SekoiaXDRAddComment.py create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRAddComment/SekoiaXDRAddComment.yml create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRAddComment/SekoiaXDRAddComment_test.py create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRChangeStatus/README.md create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRChangeStatus/SekoiaXDRChangeStatus.py create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRChangeStatus/SekoiaXDRChangeStatus.yml create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRChangeStatus/SekoiaXDRChangeStatus_test.py create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRCloseAlert/README.md create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRCloseAlert/SekoiaXDRCloseAlert.py create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRCloseAlert/SekoiaXDRCloseAlert.yml create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRCloseAlert/SekoiaXDRCloseAlert_test.py create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRPrintAssets/README.md create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRPrintAssets/SekoiaXDRPrintAssets.py create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRPrintAssets/SekoiaXDRPrintAssets.yml create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRPrintAssets/SekoiaXDRPrintAssets_test.py create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRPrintCase/README.md create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRPrintCase/SekoiaXDRPrintCase.py create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRPrintCase/SekoiaXDRPrintCase.yml create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRPrintCase/SekoiaXDRPrintCase_test.py create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRPrintComments/README.md create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRPrintComments/SekoiaXDRPrintComments.py create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRPrintComments/SekoiaXDRPrintComments.yml create mode 100644 Packs/SekoiaXDR/Scripts/SekoiaXDRPrintComments/SekoiaXDRPrintComments_test.py create mode 100644 Packs/SekoiaXDR/pack_metadata.json diff --git a/Packs/SekoiaXDR/.pack-ignore b/Packs/SekoiaXDR/.pack-ignore new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Packs/SekoiaXDR/.secrets-ignore b/Packs/SekoiaXDR/.secrets-ignore new file mode 100644 index 000000000000..bb28c95e533b --- /dev/null +++ b/Packs/SekoiaXDR/.secrets-ignore @@ -0,0 +1,5 @@ +https://api.sekoia.io +joe.done@test.io +7.3.4.4 +https://www.sekoia.io +https://docs.sekoia.io \ No newline at end of file diff --git a/Packs/SekoiaXDR/Author_image.png b/Packs/SekoiaXDR/Author_image.png new file mode 100644 index 0000000000000000000000000000000000000000..f4786f7820338172726ab13dcb57c0a89f0cbf1f GIT binary patch literal 2711 zcmV;I3TX9-P)p|0^2LFy#mWCh_eFAD~P><$Y|^Y=tG

BlhLm)z^lNXn2Ew-2lRFUSN$z%d0xUW)OyZ zba{}c8Hn(7H2QD>78&rqIb!lD4SC{x;NQ35iNIopTW1bnJGmhRi*IU;%Eh9Ilw34S zm_|m>A&53<=s8#)M#3y$}Q_UC97ZhA(*GMNIrRM$d?>-t*l=&9w8e1H)NS&QW%AjRbOU9gZ);Z201 z|KAnu3+5SQER8I8FuZ#SD?(n#oOsn6wU@Sb{(5k-7cyRY{GB(S-7+i*79xL4zp)@g zQQepE99VzQ8~fuE_=eCMGrtBT793mekLr4v7{CJc{qZry?L$!3A2&QmQLgfI*4DO9 zP{3<7uC`X)m}kYjJ{QL)vcV!K)8vl>J&GX@A%w)^V|U@TMNdw7g?N)+TNDdZr6bxM zQ|=LkvXtH=fa}TR{=vB3s3Fv+@jcUiD6BWO+GTusZKL7n5YYJnnRj*%&K;;wG8=l) z{HWBzl=yZB;%t|#cj(`5XpAp4#^*X?SxSL(Hq+6{Ky+%2+NmzYXKUM^L=un7O9ErL zmggYgVmP`x)$gsZ|78z?@Um=e`TCqKoU++O(Md6O^YL&d2?e+s_;-gTzt8ZT2C%Oy zgj{c9TNLq)YGiy1x{}Tk?rUXMhxYVHchNiPILKwUto_la0u@i)O*Xz%xY2x$y}IiT z!|*EQhdV_x*%C6smF}J93UNbMy@Uh8iEaU0b`X=dxwU=a@X3i#QxtxbLMBCa{V@vN1sb+tzIIXy69AUHWo zgvg1N?)vI$^-j7jXccWRyE&Z)yYqqn;czgz-y=TcWiVAnfyastS>a`VZ8YBF+Hx?u zdrslwH08foE?_Djb>Xtx)_-SZavf(sgkXdBgRYN2Q%XmOw~Hv2Onf!rA&NIlllPhT zJ5M(|mp4GTp1vqp0C7Slq1+t16y=5=$^AqRZx(%vH z^M25ECj>dC7t?6YQ>^^6@P0lH?@v@n;r&SHYMx0Ua?xS1sV^KBL&l{SH9=Sa^m{j^ z-JJO2JxC{hPQIeq{gAe5?i5;_53H|$zgMmPX*1s|rNzf_k(Esf(gqAjHF}TZ5{*EjOFJ4)wS% zQbA&J=t1sxhmw~c%_|d`t11eQvd_#W1t3_st?V>$llLSja5Je%NOAp9ao4Zfs9jUn zDh?s&u~#dqB8cRM_WcT$gkvDsgQXzmj@OljzW>HF1`853*33yLQnxlk95zXLjve7r z(z1OJ-+P`CmUO+6Pbt`I%<{zJytV5JigUbREX*(Jn!^fwCCms|Eb!3$=0k7mM|2AFlIWRG5q~Ia@=y+PEmQ(XbZJjc zmuc-f(PC5W3kCjhv57*92Y6Penm9j3cE?a|LbN{GsBAWy#!44mqg&&H4|(_zI&V#N zBWJ_9b=6&`83-pyo>&lT^=)I5gzI>jw8bAY|FjYEIDCI1GzDV?SF|4=?;rGJ(m~f) z0nQ-M6iJGF52`cDu{9$eSuu~dt@Kad4$t;Jx2h4F0d z)rGP)HJ9AP8@V=!vQvFSxVGf-V_qlAeDn#Fz29B20+Qmt%kvZ{9vlaol!R*ubf z49)v&dKL%ahOM94tZEx;974SEORFO9l1a{>}b&}Pu(L;e&Due z*?f7jBRz&_&6~&jF!iTN*r_xsg-OtNxtw4Ml^!d7hNpl%mAFPNQ@2xen6J|-;+wwn z7B#0hIi(OFyJg&R#=vRnYsuJm)U1y!i>zW9En5`%*qgUJi`61i2h))rTWn8WXl@5q z1T8_4C~Li0tOgkY%Qr3nlbSKA^~Rr8@fL(B`{eQiEWRq-{Eg}KAH7QT4?mIb{wrUT zkja8^uTpvOnSXrz zz2{bbM}q#>LK!Cumgrnk_o_`q8tVS4UJ13BkJ2JazVZ@=+;#Ev`>LVA1w38$^w(W@ zY;>|>D84CiqejF2s$L1Tm=Bycpy=NT%YqNU`Ha;5H|g7Au7DM|Mx&&tUH1NznSr>a zY`kr)_LsrJ0#?Wr@Q!SmrH2#AKMlj~A`J)&3kwSi3kwSi3kwSi3k!=?;(t|x>PRM| RfiwUB002ovPDHLkV1lE@B1r%M literal 0 HcmV?d00001 diff --git a/Packs/SekoiaXDR/Classifiers/classifier-Sekoia_XDR_-_Classifier.json b/Packs/SekoiaXDR/Classifiers/classifier-Sekoia_XDR_-_Classifier.json new file mode 100644 index 000000000000..276313f43639 --- /dev/null +++ b/Packs/SekoiaXDR/Classifiers/classifier-Sekoia_XDR_-_Classifier.json @@ -0,0 +1,23 @@ +{ + "defaultIncidentType": "Sekoia XDR", + "description": "", + "feed": false, + "id": "Sekoia XDR - Classifier", + "keyTypeMap": { + "malware": "Sekoia XDR", + "masquerade": "Sekoia XDR", + "phishing": "Sekoia XDR", + "ransomware": "Sekoia XDR", + "system-compromise": "Sekoia XDR" + }, + "name": "Sekoia XDR - Classifier", + "propagationLabels": [ + "all" + ], + "transformer": { + "simple": "alert_type.value" + }, + "type": "classification", + "version": -1, + "fromVersion": "6.10.0" +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Classifiers/classifier-Sekoia_XDR_-_Incoming_Mapper.json b/Packs/SekoiaXDR/Classifiers/classifier-Sekoia_XDR_-_Incoming_Mapper.json new file mode 100644 index 000000000000..23899994b7b2 --- /dev/null +++ b/Packs/SekoiaXDR/Classifiers/classifier-Sekoia_XDR_-_Incoming_Mapper.json @@ -0,0 +1,126 @@ +{ + "description": "Maps incoming Sekoia XDR incidents fields.\n", + "feed": false, + "id": "Sekoia XDR - Incoming Mapper", + "mapping": { + "Sekoia XDR": { + "dontMapEventToLabels": true, + "internalMapping": { + "Alert Category": { + "simple": "alert_type.category" + }, + "Alert ID": { + "simple": "short_id" + }, + "Alert Name": { + "simple": "title" + }, + "Alert Type ID": { + "simple": "alert_type.value" + }, + "Description": { + "simple": "details" + }, + "External Link": { + "simple": "target" + }, + "Last Seen": { + "simple": "last_seen_at" + }, + "SekoiaXDR Alert Details": { + "simple": "details" + }, + "SekoiaXDR Alert Status": { + "simple": "status.name" + }, + "SekoiaXDR First Seen": { + "simple": "first_seen_at" + }, + "SekoiaXDR Kill Chain": { + "complex": { + "filters": [], + "root": "kill_chain", + "transformers": [] + } + }, + "Source Create time": { + "complex": { + "filters": [], + "root": "created_at", + "transformers": [ + { + "operator": "TimeStampToDate" + } + ] + } + }, + "Source IP": { + "simple": "source" + }, + "dbotMirrorInstance": { + "simple": "mirror_instance" + } + } + }, + "dbot_classification_incident_type_all": { + "dontMapEventToLabels": false, + "internalMapping": { + "Alert Category": { + "simple": "alert_type.category" + }, + "Alert ID": { + "simple": "short_id" + }, + "Alert Name": { + "simple": "title" + }, + "Alert Type ID": { + "simple": "alert_type.value" + }, + "Description": { + "simple": "details" + }, + "Last Seen": { + "simple": "last_seen_at" + }, + "SekoiaXDR Alert Details": { + "simple": "details" + }, + "SekoiaXDR Alert Status": { + "simple": "status.name" + }, + "SekoiaXDR First Seen": { + "simple": "first_seen_at" + }, + "SekoiaXDR Kill Chain": { + "complex": { + "filters": [], + "root": "kill_chain", + "transformers": [] + } + }, + "Source Create time": { + "complex": { + "filters": [], + "root": "created_at", + "transformers": [ + { + "operator": "TimeStampToDate" + } + ] + } + }, + "Source IP": { + "simple": "source" + }, + "dbotMirrorInstance": { + "simple": "mirror_instance" + } + } + } + }, + "name": "Sekoia XDR - Incoming Mapper", + "type": "mapping-incoming", + "version": -1, + "fromVersion": "6.10.0" +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_alertdetails_field.json b/Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_alertdetails_field.json new file mode 100644 index 000000000000..36515a8bf2d9 --- /dev/null +++ b/Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_alertdetails_field.json @@ -0,0 +1,31 @@ +{ + "id": "incident_sekoiaxdralertdetails", + "version": -1, + "modified": "2024-07-02T13:34:47.794510655Z", + "name": "SekoiaXDR Alert Details", + "ownerOnly": false, + "cliName": "sekoiaxdralertdetails", + "type": "markdown", + "closeForm": false, + "editForm": true, + "required": false, + "neverSetAsRequired": false, + "isReadOnly": false, + "useAsKpi": false, + "locked": false, + "system": false, + "content": true, + "group": 0, + "hidden": false, + "openEnded": false, + "associatedTypes": [ + "Sekoia XDR" + ], + "associatedToAll": false, + "unmapped": false, + "unsearchable": true, + "caseInsensitive": true, + "sla": 0, + "threshold": 72, + "fromVersion": "6.10.0" +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_alertreject_field.json b/Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_alertreject_field.json new file mode 100644 index 000000000000..56dcb3238871 --- /dev/null +++ b/Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_alertreject_field.json @@ -0,0 +1,31 @@ +{ + "id": "incident_sekoiaxdralertreject", + "version": -1, + "modified": "2024-08-07T10:24:42.847046678Z", + "name": "SekoiaXDR Alert Reject", + "ownerOnly": false, + "cliName": "sekoiaxdralertreject", + "type": "boolean", + "closeForm": true, + "editForm": false, + "required": false, + "neverSetAsRequired": false, + "isReadOnly": false, + "useAsKpi": false, + "locked": false, + "system": false, + "content": true, + "group": 0, + "hidden": false, + "openEnded": false, + "associatedTypes": [ + "Sekoia XDR" + ], + "associatedToAll": false, + "unmapped": false, + "unsearchable": true, + "caseInsensitive": true, + "sla": 0, + "threshold": 72, + "fromVersion": "6.10.0" +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_alertstatus_field.json b/Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_alertstatus_field.json new file mode 100644 index 000000000000..655185060668 --- /dev/null +++ b/Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_alertstatus_field.json @@ -0,0 +1,31 @@ +{ + "id": "incident_sekoiaxdralertstatus", + "version": -1, + "modified": "2024-07-02T13:34:47.866877854Z", + "name": "SekoiaXDR Alert Status", + "ownerOnly": false, + "cliName": "sekoiaxdralertstatus", + "type": "shortText", + "closeForm": false, + "editForm": true, + "required": false, + "neverSetAsRequired": false, + "isReadOnly": false, + "useAsKpi": false, + "locked": false, + "system": false, + "content": true, + "group": 0, + "hidden": false, + "openEnded": false, + "associatedTypes": [ + "Sekoia XDR" + ], + "associatedToAll": false, + "unmapped": false, + "unsearchable": true, + "caseInsensitive": true, + "sla": 0, + "threshold": 72, + "fromVersion": "6.10.0" +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_firstseen_field.json b/Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_firstseen_field.json new file mode 100644 index 000000000000..9ff7ac804d74 --- /dev/null +++ b/Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_firstseen_field.json @@ -0,0 +1,31 @@ +{ + "id": "incident_sekoiaxdrfirstseen", + "version": -1, + "modified": "2024-07-02T13:34:47.978554181Z", + "name": "SekoiaXDR First Seen", + "ownerOnly": false, + "cliName": "sekoiaxdrfirstseen", + "type": "shortText", + "closeForm": false, + "editForm": true, + "required": false, + "neverSetAsRequired": false, + "isReadOnly": false, + "useAsKpi": false, + "locked": false, + "system": false, + "content": true, + "group": 0, + "hidden": false, + "openEnded": false, + "associatedTypes": [ + "Sekoia XDR" + ], + "associatedToAll": false, + "unmapped": false, + "unsearchable": true, + "caseInsensitive": true, + "sla": 0, + "threshold": 72, + "fromVersion": "6.10.0" +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_killchain_field.json b/Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_killchain_field.json new file mode 100644 index 000000000000..1aa70d8518cd --- /dev/null +++ b/Packs/SekoiaXDR/IncidentFields/incident_sekoia_xdr_killchain_field.json @@ -0,0 +1,62 @@ +{ + "id": "incident_sekoiaxdrkillchain", + "version": -1, + "modified": "2024-07-02T13:34:48.058774798Z", + "name": "SekoiaXDR Kill Chain", + "ownerOnly": false, + "cliName": "sekoiaxdrkillchain", + "type": "grid", + "closeForm": false, + "editForm": true, + "required": false, + "neverSetAsRequired": false, + "isReadOnly": true, + "useAsKpi": false, + "locked": false, + "system": false, + "content": true, + "group": 0, + "hidden": false, + "openEnded": false, + "associatedTypes": [ + "Sekoia XDR" + ], + "associatedToAll": false, + "unmapped": false, + "unsearchable": true, + "caseInsensitive": true, + "columns": [ + { + "key": "name", + "displayName": "Name", + "type": "shortText", + "orgType": "shortText", + "required": false, + "script": "", + "width": 150, + "isDefault": true, + "fieldCalcScript": "", + "isReadOnly": false, + "selectValues": null + }, + { + "key": "description", + "displayName": "Description", + "type": "shortText", + "orgType": "shortText", + "required": false, + "script": "", + "width": 150, + "isDefault": true, + "fieldCalcScript": "", + "isReadOnly": false, + "selectValues": null + } + ], + "defaultRows": [ + {} + ], + "sla": 0, + "threshold": 72, + "fromVersion": "6.10.0" +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/IncidentTypes/Sekoia_XDR_Incident_Types.json b/Packs/SekoiaXDR/IncidentTypes/Sekoia_XDR_Incident_Types.json new file mode 100644 index 000000000000..db5e8eb16ee0 --- /dev/null +++ b/Packs/SekoiaXDR/IncidentTypes/Sekoia_XDR_Incident_Types.json @@ -0,0 +1,56 @@ +{ + "id": "Sekoia XDR", + "version": -1, + "vcShouldIgnore": false, + "locked": false, + "name": "Sekoia XDR", + "prevName": "Sekoia XDR", + "color": "#CFD0D0", + "hours": 0, + "days": 0, + "weeks": 0, + "hoursR": 0, + "daysR": 0, + "weeksR": 0, + "system": false, + "readonly": false, + "default": false, + "autorun": false, + "closureScript": "CloseSekoiaAlert", + "disabled": false, + "reputationCalc": 2, + "onChangeRepAlg": 3, + "layout": "Sekoia XDR Layout", + "detached": false, + "extractSettings": { + "mode": "Specific", + "fieldCliNameToExtractSettings": { + "additionalemailaddresses": { + "extractAsIsIndicatorTypeId": "emailRep", + "isExtractingAllIndicatorTypes": false, + "extractIndicatorTypesIDs": [] + }, + "domainname": { + "extractAsIsIndicatorTypeId": "domainRepUnified", + "isExtractingAllIndicatorTypes": false, + "extractIndicatorTypesIDs": [] + }, + "externallink": { + "extractAsIsIndicatorTypeId": "urlRep", + "isExtractingAllIndicatorTypes": false, + "extractIndicatorTypesIDs": [] + }, + "filehash": { + "extractAsIsIndicatorTypeId": "unifiedFileRep", + "isExtractingAllIndicatorTypes": false, + "extractIndicatorTypesIDs": [] + }, + "sourceip": { + "extractAsIsIndicatorTypeId": "ipRep", + "isExtractingAllIndicatorTypes": false, + "extractIndicatorTypesIDs": [] + } + } + }, + "fromVersion": "6.10.0" +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/README.md b/Packs/SekoiaXDR/Integrations/SekoiaXDR/README.md new file mode 100644 index 000000000000..bf55af08538b --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/README.md @@ -0,0 +1,779 @@ +Fetch alerts and events from SEKOIA.IO XDR. +To use this integration, please create an API Key with the appropriate permissions. +This integration was integrated and tested with version 1.0 of Sekoia XDR. + +## Configure Sekoia XDR on Cortex XSOAR + +1. Navigate to **Settings** > **Integrations** > **Servers & Services**. +2. Search for Sekoia XDR. +3. Click **Add instance** to create and configure a new integration instance. + + | **Parameter** | **Description** | **Required** | + | --- | --- | --- | + | API key | | True | + | API Key | | True | + | Server URL (i.e. https://api.sekoia.io) | | True | + | Trust any certificate (not secure) | | False | + | Use system proxy settings | | False | + | Fetch incidents | | False | + | Incident type | | False | + | First fetch timestamp (<sign + or -><number><time unit>, e.g., -7d, -1h) | | True | + | Maximum incidents to fetch per interval. | By default the max_fetch is set to 10 | True | + | Incidents Fetch Interval | | False | + | Alerts status. | Filter alerts to fetch by status. You can write and press enter to insert new types. | False | + | Alerts types. | Filter alerts to fetch by types. You can write and press enter to insert new types. | False | + | Alerts urgency levels ( "MINurgency,MAXurgency". i.e: 80,100 ). | Filter alerts by their urgency levels. Use the format "MINurgency, MAXurgency" | False | + | Fetch mode | If there's no max_fetch it will fetch 10 incidents by default. | True | + | Replace "dots" in event field names with another character. | Replacing dots in events will make names look pretty good for users | True | + | Events fields to exclude from the events search result. | These are the names of the headers presented in the events table. If the header is not in the dropdown list write it and press enter. | False | + | Include assets information in the alerts when fetching. | When selected, it includes the assets information in the alert when fetched from Sekoia.
And also If there's no max_fetch it will fetch 10 incidents by default. | False | + | Include kill chain information in the alerts when fetching. | When selected, it includes the kill chain information in the alert when fetched from Sekoia.
And also If there's no max_fetch it will fetch 10 incidents by default. | False | + | Timezone ( TZ format ) | This will be used to present dates in the appropiate timezones, used for comment timestamps, etc. | True | + +4. Click **Test** to validate the URLs, token, and connection. + +## Commands + +You can execute these commands from the Cortex XSOAR 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. + +### sekoia-xdr-list-alerts + +*** +Command to retrieve a list of Alerts from Sekoia XDR. + +#### Base Command + +`sekoia-xdr-list-alerts` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| limit | The number of alerts to return. The allowed range is 1-100, default is 20. Default is 20. | Optional | +| status | Match alerts by their status name (separated by commas). Possible values are: Pending, Acknowledged, Ongoing, Rejected, Closed. | Optional | +| created_at | Filter alerts by their creation dates, starting date followed by ending date, i.e: "-3d,now" , "-1w,now" or "2023-01-15,2023-01-17". | Optional | +| updated_at | Filter alerts by their update dates starting date followed by ending date, i.e: "-3d,now" , "-1w,now" or "2023-01-15,2023-01-17". | Optional | +| urgency | Filter alerts by their urgencies range in the following format: "MINurgency,MAXurgency". i.e: 80,100. | Optional | +| Alerts type | Match alerts by their categories (separated by commas). Possible values are: spam, ddos, outage, phishing, unauthorized-use-of-resources, unauthorised-information-access, appscan, scanner, brute-force, exploit. | Optional | +| sort_by | Sort the alerts by any information. Possible values are: created_at, updated_at, target, urgency, status. Default is created_at. | Optional | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.ListAlerts.updated_at | unknown | The time at which the alert was updated. | +| SekoiaXDR.ListAlerts.updated_by | unknown | The user who last updated the alert. | +| SekoiaXDR.ListAlerts.uuid | unknown | The unique identifier of the alert. | +| SekoiaXDR.ListAlerts.title | unknown | The title of the alert. | +| SekoiaXDR.ListAlerts.time_to_respond | unknown | The time it took to respond to the alert. | +| SekoiaXDR.ListAlerts.short_id | unknown | The short identifier of the alert. | +| SekoiaXDR.ListAlerts.community_uuid | unknown | The unique identifier of the community associated with the alert. | +| SekoiaXDR.ListAlerts.kill_chain_short_id | unknown | The short identifier of the kill chain associated with the alert. | +| SekoiaXDR.ListAlerts.number_of_unseen_comments | unknown | The number of unseen comments on the alert. | +| SekoiaXDR.ListAlerts.updated_by_type | unknown | The type of user who last updated the alert. | +| SekoiaXDR.ListAlerts.source | unknown | The source of the alert. | +| SekoiaXDR.ListAlerts.alert_type.value | unknown | The type of the alert. | +| SekoiaXDR.ListAlerts.alert_type.category | unknown | The category type of the alert. | +| SekoiaXDR.ListAlerts.time_to_acknowledge | unknown | The time it took to acknowledge the alert. | +| SekoiaXDR.ListAlerts.stix | unknown | The STIX data associated with the alert. | +| SekoiaXDR.ListAlerts.first_seen_at | unknown | The time the alert was first seen. | +| SekoiaXDR.ListAlerts.ttps.type | unknown | The type of the TTP associated with the alert. | +| SekoiaXDR.ListAlerts.ttps.name | unknown | The name of the TTP associated with the alert. | +| SekoiaXDR.ListAlerts.ttps.id | unknown | The unique identifier of the TTP associated with the alert. | +| SekoiaXDR.ListAlerts.ttps.description | unknown | The description of the TTP associated with the alert. | +| SekoiaXDR.ListAlerts.adversaries.type | unknown | The type of the adversary associated with the alert. | +| SekoiaXDR.ListAlerts.adversaries.name | unknown | The name of the adversary associated with the alert. | +| SekoiaXDR.ListAlerts.adversaries.id | unknown | The unique identifier of the adversary associated with the alert. | +| SekoiaXDR.ListAlerts.adversaries.description | unknown | The description of the adversary associated with the alert. | +| SekoiaXDR.ListAlerts.time_to_ingest | unknown | The time it took to ingest the alert. | +| SekoiaXDR.ListAlerts.target | unknown | The target of the alert. | +| SekoiaXDR.ListAlerts.time_to_resolve | unknown | The time it took to resolve the alert. | +| SekoiaXDR.ListAlerts.created_at | unknown | The time at which the alert was created. | +| SekoiaXDR.ListAlerts.last_seen_at | unknown | The time at which the alert was last seen. | +| SekoiaXDR.ListAlerts.assets | unknown | The assets associated with the alert. | +| SekoiaXDR.ListAlerts.rule.severity | unknown | The severity level of the rule that triggered the alert. | +| SekoiaXDR.ListAlerts.rule.type | unknown | The type of rule that triggered the alert. | +| SekoiaXDR.ListAlerts.rule.uuid | unknown | The unique identifier of the rule that triggered the alert. | +| SekoiaXDR.ListAlerts.rule.name | unknown | The name of the rule that triggered the alert. | +| SekoiaXDR.ListAlerts.rule.description | unknown | The description of the rule that triggered the alert. | +| SekoiaXDR.ListAlerts.rule.pattern | unknown | The pattern of the rule that triggered the alert. | +| SekoiaXDR.ListAlerts.similar | unknown | The number of similar alerts to this one. | +| SekoiaXDR.ListAlerts.status.name | unknown | The name of the status of the alert. | +| SekoiaXDR.ListAlerts.status.description | unknown | The description of the status of the alert. | +| SekoiaXDR.ListAlerts.status.uuid | unknown | The unique identifier of the status of the alert. | +| SekoiaXDR.ListAlerts.urgency.criticity | unknown | The level of criticity of the urgency of the alert. | +| SekoiaXDR.ListAlerts.urgency.current_value | unknown | The current value of the urgency of the alert. | +| SekoiaXDR.ListAlerts.urgency.severity | unknown | The severity level of the urgency of the alert. | +| SekoiaXDR.ListAlerts.urgency.display | unknown | The display of the urgency of the alert. | +| SekoiaXDR.ListAlerts.urgency.value | unknown | The value of the urgency of the alert. | +| SekoiaXDR.ListAlerts.created_by | unknown | The user who created the alert. | +| SekoiaXDR.ListAlerts.number_of_total_comments | unknown | The total number of comments on the alert. | +| SekoiaXDR.ListAlerts.time_to_detect | unknown | The time it took to detect the alert. | +| SekoiaXDR.ListAlerts.entity.name | unknown | The name of the entity associated with the alert. | +| SekoiaXDR.ListAlerts.entity.uuid | unknown | The unique identifier of the entity associated with the alert. | +| SekoiaXDR.ListAlerts.created_by_type | unknown | The type of user who created the alert. | +| SekoiaXDR.ListAlerts.details | unknown | The details of the alert. | + +### sekoia-xdr-get-alert + +*** +Command to retrieve a specific alert by uuid or short_id from Sekoia XDR. + +#### Base Command + +`sekoia-xdr-get-alert` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| id | The uuid or short_id of the alert to retrieve from sekoia-xdr-list-alerts or from sekoia plateform. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga". | Required | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Alert.short_id | string | Short ID of the alert. | +| SekoiaXDR.Alert.title | string | Title of the alert. | +| SekoiaXDR.Alert.urgency | string | urgency of the alert. | + +### sekoia-xdr-events-execute-query + +*** +Command to create an event search job on Sekoia XDR, after this execute "sekoia-xdr-status-events-query" to see the status of the query job and "sekoia-xdr-results-events-query" to retrieve the results.. + +#### Base Command + +`sekoia-xdr-events-execute-query` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| earliest_time | Valid formats <sign + or -><number><time unit> or ISO 8601 e.g -3d, -2w, -7d, 2023-01-15T00:00:00Z. | Required | +| lastest_time | Valid formats <sign + or -><number><time unit> or ISO 8601 e.g +3d, +2w, now, 2023-01-15T00:00:00Z. | Required | +| query | The query to use, i.e: "alert_short_ids:ALUnyZCYZ9Ga". | Optional | +| max_last_events | Maximum number of listed events. | Optional | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Events.Query.uuid | unknown | The unique identifier for the event. | +| SekoiaXDR.Events.Query.term | unknown | The search term associated with the event. | +| SekoiaXDR.Events.Query.started_at | unknown | The time at which the event started. | +| SekoiaXDR.Events.Query.short_histogram.cases | unknown | The number of cases associated with the event. | +| SekoiaXDR.Events.Query.short_histogram.total | unknown | The total number of events associated with the search term. | +| SekoiaXDR.Events.Query.short_histogram.alerts | unknown | The number of alerts associated with the event. | +| SekoiaXDR.Events.Query.short_histogram.earliest_time | unknown | The earliest time associated with the event. | +| SekoiaXDR.Events.Query.short_histogram.length | unknown | The length of the histogram for the event. | +| SekoiaXDR.Events.Query.created_by | unknown | The user who created the event. | +| SekoiaXDR.Events.Query.expired | unknown | A boolean indicating whether the event has expired. | +| SekoiaXDR.Events.Query.latest_time | unknown | The latest time associated with the event. | +| SekoiaXDR.Events.Query.expiration_date | unknown | The date on which the event will expire. | +| SekoiaXDR.Events.Query.created_at | unknown | The time at which the event was created. | +| SekoiaXDR.Events.Query.status | unknown | The status of the event. | +| SekoiaXDR.Events.Query.view_uuid | unknown | The unique identifier for the view associated with the event. | +| SekoiaXDR.Events.Query.canceled_at | unknown | The time at which the event was canceled. | +| SekoiaXDR.Events.Query.only_eternal | unknown | A boolean indicating whether the event is only eternal. | +| SekoiaXDR.Events.Query.results_ttl | unknown | The time-to-live for the event results. | +| SekoiaXDR.Events.Query.canceled_by | unknown | The user who canceled the event. | +| SekoiaXDR.Events.Query.term_lang | unknown | The language of the search term associated with the event. | +| SekoiaXDR.Events.Query.ended_at | unknown | The time at which the event ended. | +| SekoiaXDR.Events.Query.earliest_time | unknown | The earliest time associated with the event. | +| SekoiaXDR.Events.Query.max_last_events | unknown | The maximum number of events to include in the results. | +| SekoiaXDR.Events.Query.canceled_by_type | unknown | The type of the user who canceled the event. | +| SekoiaXDR.Events.Query.total | unknown | The total number of events associated with the event. | +| SekoiaXDR.Events.Query.created_by_type | unknown | The type of the user who created the event. | +| SekoiaXDR.Events.Query.community_uuids | unknown | The list of community UUIDs associated with the event. | +| SekoiaXDR.Events.Query.filters.field | unknown | The field associated with the filter. | +| SekoiaXDR.Events.Query.filters.value | unknown | The value associated with the filter. | +| SekoiaXDR.Events.Query.filters.operator | unknown | The operator used in the filter. | +| SekoiaXDR.Events.Query.filters.excluded | unknown | Indicates whether the filter is excluded or not. | +| SekoiaXDR.Events.Query.filters.disabled | unknown | Indicates whether the filter is disabled or not. | + +### sekoia-xdr-events-status-query + +*** +Command to query the status of the search job on Sekoia XDR. + +#### Base Command + +`sekoia-xdr-events-status-query` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| uuid | UUID of the query executed previously with the "sekoia-xdr-query-events" command. | Required | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Events.Status.uuid | unknown | The unique identifier for the event. | +| SekoiaXDR.Events.Status.term | unknown | The term associated with the event. | +| SekoiaXDR.Events.Status.started_at | unknown | The time at which the event started. | +| SekoiaXDR.Events.Status.short_histogram.cases | unknown | The number of cases associated with the event. | +| SekoiaXDR.Events.Status.short_histogram.total | unknown | The total number of events associated with the event. | +| SekoiaXDR.Events.Status.short_histogram.alerts | unknown | The number of alerts associated with the event. | +| SekoiaXDR.Events.Status.short_histogram.earliest_time | unknown | The earliest time associated with the event. | +| SekoiaXDR.Events.Status.short_histogram.length | unknown | The length associated with the event. | +| SekoiaXDR.Events.Status.created_by | unknown | The user who created the event. | +| SekoiaXDR.Events.Status.expired | unknown | Whether the event is expired. | +| SekoiaXDR.Events.Status.latest_time | unknown | The latest time associated with the event. | +| SekoiaXDR.Events.Status.expiration_date | unknown | The date when the event expires. | +| SekoiaXDR.Events.Status.created_at | unknown | The time when the event was created. | +| SekoiaXDR.Events.Status.status | unknown | The current status of the event. | +| SekoiaXDR.Events.Status.view_uuid | unknown | The view associated with the event. | +| SekoiaXDR.Events.Status.canceled_at | unknown | The time when the event was canceled. | +| SekoiaXDR.Events.Status.only_eternal | unknown | Whether only eternal events are associated with the event. | +| SekoiaXDR.Events.Status.results_ttl | unknown | The time-to-live for the event results. | +| SekoiaXDR.Events.Status.canceled_by | unknown | The user who canceled the event. | +| SekoiaXDR.Events.Status.term_lang | unknown | The language associated with the term for the event. | +| SekoiaXDR.Events.Status.ended_at | unknown | The time when the event ended. | +| SekoiaXDR.Events.Status.earliest_time | unknown | The earliest time associated with the event. | +| SekoiaXDR.Events.Status.max_last_events | unknown | The maximum number of events to retrieve. | +| SekoiaXDR.Events.Status.canceled_by_type | unknown | The type of user who canceled the event. | +| SekoiaXDR.Events.Status.total | unknown | The total number of events associated with the event. | +| SekoiaXDR.Events.Status.created_by_type | unknown | The type of user who created the event. | +| SekoiaXDR.Events.Status.community_uuids[0] | unknown | The community associated with the event. | +| SekoiaXDR.Events.Status.filters.field | unknown | The field used for filtering events. | +| SekoiaXDR.Events.Status.filters.field | unknown | The field used in the filter. | +| SekoiaXDR.Events.Status.filters.value | unknown | The value of the filter. | +| SekoiaXDR.Events.Status.filters.operator | unknown | The operator used in the filter. | +| SekoiaXDR.Events.Status.filters.excluded | unknown | A boolean indicating whether the filter is excluded or not. | +| SekoiaXDR.Events.Status.filters.disabled | unknown | A boolean indicating whether the filter is disabled or not. | + +### sekoia-xdr-events-results-query + +*** +Command to retrieve the events from the search job "sekoia-xdr-execute-events-query" previously done on Sekoia XDR. + +#### Base Command + +`sekoia-xdr-events-results-query` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| uuid | UUID from response of the query executed previously with the "sekoia-xdr-query-events" command. | Required | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Events.Results | unknown | The outputs are different for each event, they will be output inside SekoiaXDR.Events.Results. | + +### sekoia-xdr-search-events + +*** +Command to search and retrieve the events from an alert. This is a combination of 3 commands: sekoia-xdr-events-execute-query, sekoia-xdr-events-status-query and sekoia-xdr-events-results-query. + +#### Base Command + +`sekoia-xdr-search-events` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| earliest_time | Valid formats <sign + or -><number><time unit> or ISO 8601 e.g -3d, -2w, -7d, 2023-01-15T00:00:00Z. | Required | +| lastest_time | Valid formats <sign + or -><number><time unit> or ISO 8601 e.g +3d, +2w, now, 2023-01-15T00:00:00Z. | Required | +| query | The query to use, i.e: "alert_short_ids:ALUnyZCYZ9Ga". | Optional | +| max_last_events | Maximum number of listed events. | Optional | +| exclude_info | Indicate if there is any information you want to exclude from the results of the events. i.e: original.message, message, agent.name, etc. These are the names of the headers presented in the table. If the header you want to exclude is not in the list write it and press enter. Possible values are: original.message, message, __event_id, agent.name, alert_short_ids, client.address, client.ip, client.user.id, customer.community_name, customer.community_uuid, customer.id, customer.intake_key, customer.intake_name, customer.intake_uuid, ecs.version, entity.id, entity.name, entity.uuid, event.created, event.dialect, event.dialect_uuid, event.id, event.outcome, http.request.method, http.request.referrer, related.ip, sekoiaio.activity.client.id, sekoiaio.activity.client.type, sekoiaio.customer.community_name, sekoiaio.customer.community_uuid, sekoiaio.customer.id, sekoiaio.entity.id, sekoiaio.entity.name, sekoiaio.entity.uuid, sekoiaio.intake.dialect, sekoiaio.intake.dialect_uuid, sekoiaio.intake.key, sekoiaio.intake.name, sekoiaio.intake.parsing_status, sekoiaio.intake.uuid, timestamp, url.domain, url.original, url.path, url.port, url.query, url.registered_domain, url.scheme, url.subdomain, url.top_level_domain, user_agent.original. | Optional | +| job_uuid | The job UUID to retrieve query results. | Optional | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Events.Results | unknown | The outputs are different for each event, they will be output inside SekoiaXDR.Events.Results. | + +### sekoia-xdr-update-status-alert + +*** +Command to update the status of a specific Alert by uuid or short_id. + +#### Base Command + +`sekoia-xdr-update-status-alert` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| id | The uuid or short_id of the alert to retrieve from sekoia-xdr-list-alerts or from sekoia plateform. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga". | Required | +| status | The status you want to apply. (Acknowledged, Rejected, Ongoing, Closed)). Possible values are: Acknowledged, Rejected, Ongoing, Closed. | Required | +| comment | Comment to describe why the alert status has changed. | Optional | + +#### Context Output + +There is no context output for this command. + +### sekoia-xdr-post-comment-alert + +*** +Command to post comments to alerts in Sekoia XDR. + +#### Base Command + +`sekoia-xdr-post-comment-alert` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| id | The uuid or short_id of the alert to retrieve from sekoia-xdr-list-alerts command. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga". | Required | +| comment | Content of the comment to be posted on the alert. | Required | +| author | Author of the comment. | Optional | + +#### Context Output + +There is no context output for this command. + +### sekoia-xdr-get-comments + +*** +Command to get all the comments from an alert in Sekoia XDR. + +#### Base Command + +`sekoia-xdr-get-comments` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| id | The uuid or short_id of the alert to retrieve from sekoia-xdr-list-alerts command or from sekoia plateform. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga". | Required | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Comments.total | unknown | The total number of items in the comments. | +| SekoiaXDR.Comments.items.date | unknown | The date at which the comment was created. | +| SekoiaXDR.Comments.items.created_by | unknown | The user who created the comment. | +| SekoiaXDR.Comments.items.uuid | unknown | The unique identifier for the comment. | +| SekoiaXDR.Comments.items.content | unknown | The content of the comment. | +| SekoiaXDR.Comments.items.created_by_type | unknown | The type of the user who created the comment. | +| SekoiaXDR.Comments.items.unseen | unknown | Indicates whether the comment has been seen by the user. | +| SekoiaXDR.Comments.items.author | unknown | The author of the comment. | + +### sekoia-xdr-get-workflow-alert + +*** +Command to get the possible transitions of status on the alert. + +#### Base Command + +`sekoia-xdr-get-workflow-alert` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| id | The uuid or short_id of the alert to retrieve from sekoia-xdr-list-alerts command or from sekoia plateform. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga". | Required | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.StatusTransitions.actions.name | unknown | The name of the action. | +| SekoiaXDR.StatusTransitions.actions.description | unknown | The description of the action. | +| SekoiaXDR.StatusTransitions.actions.id | unknown | The ID of the action. | + +### sekoia-xdr-get-cases-alert + +*** +Command to retrieve the cases related to an Alert from Sekoia XDR. If a case_id is given, returns the information about it, and if not it will give all cases in this alert. + +#### Base Command + +`sekoia-xdr-get-cases-alert` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| alert_id | The uuid or short_id of the alert to retrieve from sekoia-xdr-list-alerts command or from sekoia plateform. i.e: "f5dcb81c-8d81-4332-9f1e-f119a1b31217" or "ALUnyZCYZ9Ga". | Required | +| case_id | The short_id of the case to retrieve from sekoia plateform or from this command without case_is param i.e: "CAQNurTJM8q2". | Optional | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Cases.updated_at | unknown | The time at which the case was updated. | +| SekoiaXDR.Cases.updated_by | unknown | The user who updated the case. | +| SekoiaXDR.Cases.uuid | unknown | The unique identifier of the case. | +| SekoiaXDR.Cases.title | unknown | The title of the case. | +| SekoiaXDR.Cases.priority | unknown | The priority level of the case. | +| SekoiaXDR.Cases.short_id | unknown | The short ID of the case. | +| SekoiaXDR.Cases.community_uuid | unknown | The unique identifier of the community to which the case belongs. | +| SekoiaXDR.Cases.updated_by_type | unknown | The type of user who updated the case. | +| SekoiaXDR.Cases.first_seen_at | unknown | The time at which the case was first seen. | +| SekoiaXDR.Cases.number_of_comments | unknown | The number of comments on the case. | +| SekoiaXDR.Cases.alerts.updated_at | unknown | The time at which the alert was updated. | +| SekoiaXDR.Cases.alerts.updated_by | unknown | The user who updated the alert. | +| SekoiaXDR.Cases.alerts.uuid | unknown | The unique identifier of the alert. | +| SekoiaXDR.Cases.alerts.title | unknown | The title of the alert. | +| SekoiaXDR.Cases.alerts.time_to_respond | unknown | The time it took to respond to the alert. | +| SekoiaXDR.Cases.alerts.short_id | unknown | The short ID of the alert. | +| SekoiaXDR.Cases.alerts.community_uuid | unknown | The unique identifier of the community to which the alert belongs. | +| SekoiaXDR.Cases.alerts.kill_chain_short_id | unknown | The short ID of the kill chain. | +| SekoiaXDR.Cases.alerts.number_of_unseen_comments | unknown | The number of unseen comments on the alert. | +| SekoiaXDR.Cases.alerts.updated_by_type | unknown | The type of user who updated the alert. | +| SekoiaXDR.Cases.alerts.source | unknown | The source of the alert. | +| SekoiaXDR.Cases.alerts.alert_type.value | unknown | The type of the alert. | +| SekoiaXDR.Cases.alerts.alert_type.category | unknown | The category type of the alert. | +| SekoiaXDR.Cases.alerts.time_to_acknowledge | unknown | The time it took to acknowledge the alert. | +| SekoiaXDR.Cases.alerts.stix | unknown | The STIX data of the alert. | +| SekoiaXDR.Cases.alerts.first_seen_at | unknown | The time at which the alert was first seen. | +| SekoiaXDR.Cases.alerts.ttps.type | unknown | The type of TTP associated with the alert. | +| SekoiaXDR.Cases.alerts.ttps.name | unknown | The name of the TTP associated with the alert. | +| SekoiaXDR.Cases.alerts.ttps.id | unknown | The ID of the TTP associated with the alert. | +| SekoiaXDR.Cases.alerts.ttps.description | unknown | The description of the TTP associated with the alert. | +| SekoiaXDR.Cases.alerts.adversaries.type | unknown | The type of adversary associated with the alert. | +| SekoiaXDR.Cases.alerts.adversaries.name | unknown | The name of the adversary associated with the alert. | +| SekoiaXDR.Cases.alerts.adversaries.id | unknown | The ID of the adversary associated with the alert. | +| SekoiaXDR.Cases.alerts.adversaries.description | unknown | The description of the adversary associated with the alert. | +| SekoiaXDR.Cases.alerts.time_to_ingest | unknown | The time it took to ingest the alert. | +| SekoiaXDR.Cases.alerts.target | unknown | The target of the alert. | +| SekoiaXDR.Cases.alerts.time_to_resolve | unknown | The time it took to resolve the alert. | +| SekoiaXDR.Cases.alerts.created_at | unknown | The time at which the alert was created. | +| SekoiaXDR.Cases.alerts.last_seen_at | unknown | The time at which the alert was last seen. | +| SekoiaXDR.Cases.alerts.assets | unknown | The assets associated with the alert. | +| SekoiaXDR.Cases.alerts.rule.severity | unknown | The severity level of the rule associated with the alert. | +| SekoiaXDR.Cases.alerts.rule.type | unknown | The type of rule associated with the alert. | +| SekoiaXDR.Cases.alerts.rule.uuid | unknown | The unique identifier of the rule associated with the alert. | +| SekoiaXDR.Cases.alerts.rule.name | unknown | The name of the rule associated with the alert. | +| SekoiaXDR.Cases.alerts.rule.description | unknown | The description of the rule associated with the alert. | +| SekoiaXDR.Cases.alerts.rule.pattern | unknown | The pattern of the rule associated with the alert. | +| SekoiaXDR.Cases.alerts.similar | unknown | The number of similar alerts. | +| SekoiaXDR.Cases.alerts.status.name | unknown | The name of the status of the alert. | +| SekoiaXDR.Cases.alerts.status.description | unknown | The description of the status of the alert. | +| SekoiaXDR.Cases.alerts.status.uuid | unknown | The unique identifier of the status of the alert. | +| SekoiaXDR.Cases.alerts.urgency.criticity | unknown | The level of criticality of the urgency of the alert. | +| SekoiaXDR.Cases.alerts.urgency.current_value | unknown | The current value of the urgency of the alert. | +| SekoiaXDR.Cases.alerts.urgency.severity | unknown | The severity level of the urgency of the alert. | +| SekoiaXDR.Cases.alerts.urgency.display | unknown | The display value of the urgency of the alert. | +| SekoiaXDR.Cases.alerts.urgency.value | unknown | The value of the urgency of the alert. | +| SekoiaXDR.Cases.alerts.created_by | unknown | The user who created the alert. | +| SekoiaXDR.Cases.alerts.number_of_total_comments | unknown | The total number of comments on the alert. | +| SekoiaXDR.Cases.alerts.time_to_detect | unknown | The time it took to detect the alert. | +| SekoiaXDR.Cases.alerts.entity.name | unknown | The name of the entity associated with the alert. | +| SekoiaXDR.Cases.alerts.entity.uuid | unknown | The unique identifier of the entity associated with the alert. | +| SekoiaXDR.Cases.alerts.created_by_type | unknown | The type of user who created the alert. | +| SekoiaXDR.Cases.alerts.details | unknown | The details of the alert. | +| SekoiaXDR.Cases.number_of_alerts | unknown | The number of alerts in the case. | +| SekoiaXDR.Cases.created_at | unknown | The time at which the case was created. | +| SekoiaXDR.Cases.last_seen_at | unknown | The time at which the case was last seen. | +| SekoiaXDR.Cases.status | unknown | The status of the case. | +| SekoiaXDR.Cases.description | unknown | The description of the case. | +| SekoiaXDR.Cases.status_uuid | unknown | The unique identifier of the status of the case. | +| SekoiaXDR.Cases.created_by | unknown | The user who created the case. | +| SekoiaXDR.Cases.tags | unknown | The tags associated with the case. | +| SekoiaXDR.Cases.created_by_type | unknown | The type of user who created the case. | +| SekoiaXDR.Cases.subscribers.avatar_uuid | unknown | The unique identifier of the avatar of the subscriber. | +| SekoiaXDR.Cases.subscribers.type | unknown | The type of subscriber. | + +### sekoia-xdr-get-asset + +*** +Get an asset by its UUID from Sekoia XDR. + +#### Base Command + +`sekoia-xdr-get-asset` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| asset_uuid | UUID of the asset to get, the UUID should appear with "sekoia-xdr-list-assets" if that alert have assets related, example: "d4cc3b05-a78d-4f29-b27c-c637d86fa03a". | Required | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Asset.owners | unknown | The owners of the asset. | +| SekoiaXDR.Asset.category.types.description | unknown | The description of the category type of the asset. | +| SekoiaXDR.Asset.category.types.name | unknown | The name of the category type of the asset. | +| SekoiaXDR.Asset.category.types.uuid | unknown | The UUID of the category type of the asset. | +| SekoiaXDR.Asset.category.description | unknown | The description of the category of the asset. | +| SekoiaXDR.Asset.category.name | unknown | The name of the category of the asset. | +| SekoiaXDR.Asset.category.uuid | unknown | The UUID of the category of the asset. | +| SekoiaXDR.Asset.created_at | unknown | The time at which the asset was created. | +| SekoiaXDR.Asset.keys.value | unknown | The value of the keys of the asset. | +| SekoiaXDR.Asset.keys.name | unknown | The name of the keys of the asset. | +| SekoiaXDR.Asset.keys.uuid | unknown | The UUID of the keys of the asset. | +| SekoiaXDR.Asset.attributes.value | unknown | The value of the attributes of the asset. | +| SekoiaXDR.Asset.attributes.name | unknown | The name of the attributes of the asset. | +| SekoiaXDR.Asset.attributes.uuid | unknown | The UUID of the attributes of the asset. | +| SekoiaXDR.Asset.updated_at | unknown | The time at which the asset was updated. | +| SekoiaXDR.Asset.asset_type.description | unknown | The description of the asset type. | +| SekoiaXDR.Asset.asset_type.name | unknown | The name of the asset type. | +| SekoiaXDR.Asset.asset_type.uuid | unknown | The UUID of the asset type. | +| SekoiaXDR.Asset.criticity.value | unknown | The criticality value of the asset. | +| SekoiaXDR.Asset.criticity.display | unknown | The display value of the criticality of the asset. | +| SekoiaXDR.Asset.description | unknown | The description of the asset. | +| SekoiaXDR.Asset.community_uuid | unknown | The UUID of the community of the asset. | +| SekoiaXDR.Asset.name | unknown | The name of the asset. | +| SekoiaXDR.Asset.uuid | unknown | The UUID of the asset. | + + +### sekoia-xdr-list-assets + +*** +Command to retrieve a list of Assets from Sekoia XDR. + +#### Base Command + +`sekoia-xdr-list-assets` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| limit | Limit a number of items. Default is 10. | Optional | +| assets_type | Type of assets to list (computer, network, etc). | Optional | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.Assets.total | unknown | The total number of items in the response. | +| SekoiaXDR.Assets.items.0.owners.0 | unknown | The ID of the owner of the asset. | +| SekoiaXDR.Assets.items.0.category.types.0.description | unknown | The description of the type of the asset category. | +| SekoiaXDR.Assets.items.0.category.types.0.name | unknown | The name of the type of the asset category. | +| SekoiaXDR.Assets.items.0.category.types.0.uuid | unknown | The UUID of the type of the asset category. | +| SekoiaXDR.Assets.items.0.category.description | unknown | The description of the asset category. | +| SekoiaXDR.Assets.items.0.category.name | unknown | The name of the asset category. | +| SekoiaXDR.Assets.items.0.category.uuid | unknown | The UUID of the asset category. | +| SekoiaXDR.Assets.items.0.created_at | unknown | The time at which the asset was created. | +| SekoiaXDR.Assets.items.0.keys.0.value | unknown | The value of the asset key. | +| SekoiaXDR.Assets.items.0.keys.0.name | unknown | The name of the asset key. | +| SekoiaXDR.Assets.items.0.keys.0.uuid | unknown | The UUID of the asset key. | +| SekoiaXDR.Assets.items.0.attributes.0.value | unknown | The value of the asset attribute. | +| SekoiaXDR.Assets.items.0.attributes.0.name | unknown | The name of the asset attribute. | +| SekoiaXDR.Assets.items.0.attributes.0.uuid | unknown | The UUID of the asset attribute. | +| SekoiaXDR.Assets.items.0.updated_at | unknown | The time at which the asset was last updated. | +| SekoiaXDR.Assets.items.0.asset_type.description | unknown | The description of the asset type. | +| SekoiaXDR.Assets.items.0.asset_type.name | unknown | The name of the asset type. | +| SekoiaXDR.Assets.items.0.asset_type.uuid | unknown | The UUID of the asset type. | +| SekoiaXDR.Assets.items.0.criticity.value | unknown | The numeric value of the asset criticality. | +| SekoiaXDR.Assets.items.0.criticity.display | unknown | The display value of the asset criticality. | +| SekoiaXDR.Assets.items.0.description | unknown | The description of the asset. | +| SekoiaXDR.Assets.items.0.community_uuid | unknown | The UUID of the community to which the asset belongs. | +| SekoiaXDR.Assets.items.0.name | unknown | The name of the asset. | +| SekoiaXDR.Assets.items.0.uuid | unknown | The UUID of the asset. | + +### sekoia-xdr-get-user + +*** +Command to get information about a user in Sekoia XDR. Used also in the command !sekoia-xdr-get-comments to have the name of the persons who made the comments. + +#### Base Command + +`sekoia-xdr-get-user` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| user_uuid | UUID of the user, you get it from `sekoia-xdr-get-comments` for example. But make sure that `created_by_type` field is `user`. | Required | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.User.creator.description | unknown | The description of the creator. | +| SekoiaXDR.User.creator.name | unknown | The name of the creator. | +| SekoiaXDR.User.creator.uuid | unknown | The UUID of the creator. | +| SekoiaXDR.User.updated_at | unknown | The time at which the object was last updated. | +| SekoiaXDR.User.created_by | unknown | The UUID of the user who created the object. | +| SekoiaXDR.User.total_members | unknown | The total number of members in the community. | +| SekoiaXDR.User.subcommunities | unknown | The UUIDs of the subcommunities. | +| SekoiaXDR.User.parent_community_uuid | unknown | The UUID of the parent community. | +| SekoiaXDR.User.applications.description | unknown | The description of the application. | +| SekoiaXDR.User.applications.name | unknown | The name of the application. | +| SekoiaXDR.User.applications.uuid | unknown | The UUID of the application. | +| SekoiaXDR.User.is_parent | unknown | Whether the community is a parent community. | +| SekoiaXDR.User.name | unknown | The name of the community. | +| SekoiaXDR.User.members.uuid | unknown | The UUID of the member. | +| SekoiaXDR.User.members.created_at | unknown | The time at which the member was created. | +| SekoiaXDR.User.members.user.firstname | unknown | The first name of the user associated with the member. | +| SekoiaXDR.User.members.user.mfa_enabled | unknown | Whether multi-factor authentication is enabled for the user associated with the member. | +| SekoiaXDR.User.members.user.uuid | unknown | The UUID of the user associated with the member. | +| SekoiaXDR.User.members.user.company_name | unknown | The company name of the user associated with the member. | +| SekoiaXDR.User.members.user.lastname | unknown | The last name of the user associated with the member. | +| SekoiaXDR.User.members.user.created_at | unknown | The time at which the user associated with the member was created. | +| SekoiaXDR.User.members.user.picture_mode | unknown | The picture mode of the user associated with the member. | +| SekoiaXDR.User.members.user.last_activity | unknown | The last activity time of the user associated with the member. | +| SekoiaXDR.User.members.user.updated_at | unknown | The time at which the user associated with the member was last updated. | +| SekoiaXDR.User.members.user.auth_provider | unknown | The authentication provider of the user associated with the member. | +| SekoiaXDR.User.members.user.email | unknown | The email address of the user associated with the member. | +| SekoiaXDR.User.members.user.invitation_v2.email | unknown | The email address for the invitation associated with the user associated with the member. | +| SekoiaXDR.User.members.name | unknown | The name of the member. | +| SekoiaXDR.User.members.updated_at | unknown | The time at which the member was last updated. | +| SekoiaXDR.User.members.status_changed_at | unknown | The time at which the status of the member was last changed. | +| SekoiaXDR.User.members.status | unknown | The status of the member. | +| SekoiaXDR.User.session_timeout | unknown | The session timeout for the community. | +| SekoiaXDR.User.is_mfa_enforced | unknown | Whether multi-factor authentication is enforced for the community. | +| SekoiaXDR.User.uuid | unknown | The UUID of the community. | +| SekoiaXDR.User.created_at | unknown | The time at which the community was created. | +| SekoiaXDR.User.picture_mode | unknown | The picture mode for the community. | +| SekoiaXDR.User.homepage_url | unknown | The homepage URL for the community. | +| SekoiaXDR.User.created_by_type | unknown | The type of the user who created the community. | +| SekoiaXDR.User.disable_inactive_avatars | unknown | Whether inactive avatars are disabled for the community. | +| SekoiaXDR.User.description | unknown | The description of the community. | + +### sekoia-xdr-add-attributes-asset + +*** +Command to add attributes to an asset in Sekoia XDR. + +#### Base Command + +`sekoia-xdr-add-attributes-asset` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| asset_uuid | UUID of the asset to get, the UUID should appear with "sekoia-xdr-list-assets" if that alert have assets related, example: "d4cc3b05-a78d-4f29-b27c-c637d86fa03a". | Required | +| name | The name of attributes. | Required | +| value | The value of attributes. | Required | + +#### Context Output + +There is no context output for this command. + +### sekoia-xdr-add-keys-asset + +*** +Command to add keys to an asset in Sekoia XDR. + +#### Base Command + +`sekoia-xdr-add-keys-asset` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| asset_uuid | UUID of the asset to get, the UUID should appear with "sekoia-xdr-list-assets" if that alert have assets related, example: "d4cc3b05-a78d-4f29-b27c-c637d86fa03a". | Required | +| name | The name of the key to be added. | Required | +| value | The value of the key to be added. | Required | + +#### Context Output + +There is no context output for this command. + +### sekoia-xdr-get-kill-chain + +*** +Command to retrieve the definition of a Cyber Kill Chain Step. + +#### Base Command + +`sekoia-xdr-get-kill-chain` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| kill_chain_uuid | UUID or short_id of the kill chain the UUID should appear with "sekoia-xdr-list-alerts". | Required | + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| SekoiaXDR.KillChain.stix_name | unknown | The name of the STIX object. | +| SekoiaXDR.KillChain.description | unknown | The description of the STIX object. | +| SekoiaXDR.KillChain.name | unknown | The common name of the STIX object. | +| SekoiaXDR.KillChain.uuid | unknown | The unique identifier of the STIX object. | +| SekoiaXDR.KillChain.short_id | unknown | The short identifier of the STIX object. | +| SekoiaXDR.KillChain.order_id | unknown | The order identifier of the STIX object. | + +### sekoia-xdr-remove-attribute-asset + +*** +Command to remove an attribute from an asset in Sekoia XDR. Note: use !sekoia-xdr-get-asset to find the attribute_uuid to delete. + +#### Base Command + +`sekoia-xdr-remove-attribute-asset` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| asset_uuid | UUID of the asset, the UUID should appear with "sekoia-xdr-list-assets" if that alert have assets related, example: "d4cc3b05-a78d-4f29-b27c-c637d86fa03a". | Required | +| attribute_uuid | UUID of the attribute to delete. Note: use !sekoia-xdr-get-asset to find the attribute_uuid to delete. | Required | + +#### Context Output + +There is no context output for this command. + +### sekoia-xdr-remove-key-asset + +*** +Command to remove a key from an asset in Sekoia XDR. Note: use !sekoia-xdr-get-asset to find the key_uuid to delete. + +#### Base Command + +`sekoia-xdr-remove-key-asset` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| asset_uuid | UUID of the asset, the UUID should appear with "sekoia-xdr-list-assets" if that alert have assets related, example: "d4cc3b05-a78d-4f29-b27c-c637d86fa03a". | Required | +| key_uuid | UUID of the key to remove. Note: use !sekoia-xdr-get-asset to find the key_uuid to delete. | Required | + +#### Context Output + +There is no context output for this command. + +### sekoia-xdr-http-request + +*** +Command that performs a HTTP request to Sekoia using the integration authentication configured. + +#### Base Command + +`sekoia-xdr-http-request` + +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| method | Method to use with the http request (GET,POST,etc). Default is GET. | Required | +| url_sufix | The URL suffix after https://api.sekoia.io, i.e. /v1/sic/alerts/ or /v1/asset-management/assets/. | Required | +| parameters | Query parameters, i.e. limit -> 10 , match['status_name'] -> Ongoing. | Optional | + +#### Context Output + +There is no context output for this command. + +## Troubleshooting + +To troubleshoot possible issues with the SEKOIA XDR integration, consider the following steps: + +- **Debug Mode**: + - In your integration instance, enable the Debug option. + - Navigate to `Settings > About > Troubleshooting > Download logs` to download the logs. Analyzing these logs can provide valuable insights into any issues. + +## Additional documentation + +The following documentation can be useful to understand the integration: + +| Information | Description | +| --- | --- | +| [Post process scripts](https://docs-cortex.paloaltonetworks.com/r/Cortex-XSOAR/6.5/Cortex-XSOAR-Administrator-Guide/Post-Processing-for-Incidents) | Adittional information for post process scripts | +| [Sekoia XDR documentation](https://docs.sekoia.io/xdr/) | Sekoia XDR Documentation | +| [Rest API Documentation](https://docs.sekoia.io/xdr/develop/rest_api/alert/) | Sekoia XDR API Documentation | \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR.py b/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR.py new file mode 100644 index 000000000000..47981563abaa --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR.py @@ -0,0 +1,1248 @@ +import demistomock as demisto # noqa: F401 +from CommonServerPython import * # noqa: F401 +from CommonServerUserPython import * # noqa: F401 + +import json +import urllib3 +import dateparser # type: ignore +from typing import Any, Dict, Tuple, List, Optional, cast +from datetime import datetime +import re +import pytz # type: ignore + +# Disable insecure warnings +urllib3.disable_warnings() + + +""" CONSTANTS """ + +DATE_FORMAT = "%Y-%m-%dT%H:%M:%S" +INTERVAL_SECONDS_EVENTS = 1 +TIMEOUT_EVENTS = 30 +STATUS_TRANSITIONS = { + "Ongoing": "Validate", + "Acknowledged": "Acknowledge", + "Rejected": "Reject", + "Closed": "Close", +} + + +""" CLIENT CLASS """ + + +class Client(BaseClient): + """Client class to interact with the service API""" + + def get_validate_resource(self) -> str: + """ + Request Sekoia.io to validate the API Key + """ + try: + self._http_request( + method="GET", + url_suffix="/v1/auth/validate", + raise_on_status=True, + ) + return "ok" + except DemistoException as e: + raise DemistoException(f"Integration error: the request failed due to: {e}") + + def list_alerts( + self, + alerts_limit: Optional[int], + alerts_status: Optional[str], + alerts_created_at: Optional[str], + alerts_updated_at: Optional[str], + alerts_urgency: Optional[str], + alerts_type: Optional[str], + sort_by: Optional[str], + ) -> Dict[str, Any]: + request_params: Dict[str, Any] = {} + + """ Normal parameters""" + if alerts_limit: + request_params["limit"] = alerts_limit + + """ Matching parameters""" + if alerts_status: + request_params["match[status_name]"] = alerts_status + if alerts_created_at: + request_params["date[created_at]"] = alerts_created_at + if alerts_updated_at: + request_params["date[updated_at]"] = alerts_updated_at + if alerts_urgency: + request_params["range[urgency]"] = alerts_urgency + if alerts_type: + request_params["match[type_value]"] = alerts_type + + """ Sorting parameters""" + if sort_by: + request_params["sort"] = sort_by + + return self._http_request( + method="GET", url_suffix="/v1/sic/alerts", params=request_params + ) + + def get_alert(self, alert_uuid: str) -> Dict[str, Any]: + return self._http_request( + method="GET", url_suffix=f"/v1/sic/alerts/{alert_uuid}" + ) + + def update_status_alert( + self, alert_uuid: str, action_uuid: str, comment: Optional[str] + ) -> Dict[str, Any]: + request_params: Dict[str, Any] = {"action_uuid": action_uuid} + + """ Normal parameters""" + if comment: + request_params["comment"] = comment + + return self._http_request( + method="PATCH", + url_suffix=f"/v1/sic/alerts/{alert_uuid}/workflow", + json_data=request_params, + ) + + def post_comment_alert( + self, alert_uuid: str, content: str, author: Optional[str] + ) -> Dict[str, Any]: + request_params: Dict[str, Any] = {"content": content} + + """ Normal parameters""" + if author: + request_params["author"] = author + + return self._http_request( + method="POST", + url_suffix=f"/v1/sic/alerts/{alert_uuid}/comments", + json_data=request_params, + ) + + def get_comments_alert(self, alert_uuid: str) -> Dict[str, Any]: + return self._http_request( + method="GET", + url_suffix=f"/v1/sic/alerts/{alert_uuid}/comments", + ) + + def get_workflow_alert(self, alert_uuid: str) -> Dict[str, Any]: + return self._http_request( + method="GET", + url_suffix=f"/v1/sic/alerts/{alert_uuid}/workflow", + ) + + def query_events( + self, + events_earliest_time: str, + events_latest_time: str, + events_term: str, + max_last_events: Optional[str], + ) -> Dict[str, Any]: + request_params: Dict[str, Any] = { + "earliest_time": events_earliest_time, + "latest_time": events_latest_time, + "term": events_term, + } + + """ Normal parameters""" + if max_last_events: + request_params["max_last_events"] = max_last_events + + return self._http_request( + method="POST", + url_suffix="/v1/sic/conf/events/search/jobs", + json_data=request_params, + ) + + def query_events_status(self, event_search_job_uuid: str) -> Dict[str, Any]: + return self._http_request( + method="GET", + url_suffix=f"/v1/sic/conf/events/search/jobs/{event_search_job_uuid}", + ) + + def retrieve_events(self, event_search_job_uuid: str) -> Dict[str, Any]: + return self._http_request( + method="GET", + url_suffix=f"/v1/sic/conf/events/search/jobs/{event_search_job_uuid}/events", + ) + + def get_cases_alert( + self, alert_uuid: str, case_id: Optional[str] + ) -> Dict[str, Any]: + request_params: Dict[str, Any] = {"match[alert_uuid]": alert_uuid} + + """ Matching parameters""" + if case_id: + request_params["match[short_id]"] = case_id + + return self._http_request( + method="GET", url_suffix="v1/sic/cases", params=request_params + ) + + def get_asset(self, asset_uuid: str) -> Dict[str, Any]: + return self._http_request( + method="GET", + url_suffix=f"/v1/asset-management/assets/{asset_uuid}", + ) + + def list_asset( + self, limit: Optional[str], assets_type: Optional[str] + ) -> Dict[str, Any]: + request_params: Dict[str, Any] = {} + + """ Normal parameters""" + if limit: + request_params["limit"] = limit + + """ Matching parameters""" + if assets_type: + request_params["match[type_name]"] = assets_type + + return self._http_request( + method="GET", + url_suffix="/v1/asset-management/assets", + params=request_params, + ) + + def add_attributes_asset( + self, asset_uuid: str, name: str, value: str + ) -> Dict[str, Any]: + request_params: Dict[str, Any] = {"name": name, "value": value} + + return self._http_request( + method="POST", + url_suffix=f"/v1/asset-management/assets/{asset_uuid}/attr", + params=request_params, + ) + + def add_keys_asset(self, asset_uuid: str, name: str, value: str) -> Dict[str, Any]: + request_params: Dict[str, Any] = {"name": name, "value": value} + + return self._http_request( + method="POST", + url_suffix=f"/v1/asset-management/assets/{asset_uuid}/keys", + params=request_params, + ) + + def remove_attribute_asset( + self, asset_uuid: str, attribute_uuid: str + ) -> List[Dict[str, Any]]: + return self._http_request( + method="DELETE", + url_suffix=f"/v1/asset-management/assets/{asset_uuid}/attr/{attribute_uuid}", + resp_type="text", + ) + + def remove_key_asset(self, asset_uuid: str, key_uuid: str) -> Dict[str, Any]: + return self._http_request( + method="DELETE", + url_suffix=f"/v1/asset-management/assets/{asset_uuid}/keys/{key_uuid}", + resp_type="text", + ) + + def get_user(self, user_uuid: str) -> Dict[str, Any]: + return self._http_request(method="GET", url_suffix=f"/v1/users/{user_uuid}") + + def get_kill_chain(self, kill_chain_uuid: str) -> Dict[str, Any]: + return self._http_request( + method="GET", url_suffix=f"/v1/sic/kill-chains/{kill_chain_uuid}" + ) + + def http_request( + self, method: str, url_suffix: str, params: dict + ) -> Dict[str, Any]: + if not params: + params = {} + + return self._http_request(method=method, url_suffix=url_suffix, params=params) + + +""" HELPER FUNCTIONS """ + + +def arg_to_timestamp(arg: Any, arg_name: str, required: bool = False) -> int: + """ + Converts an XSOAR argument to a timestamp (seconds from epoch). + This function is used to quickly validate an argument provided to XSOAR + via ``demisto.args()`` into an ``int`` containing a timestamp (seconds + since epoch). It will throw a ValueError if the input is invalid. + If the input is None, it will throw a ValueError if required is ``True``, + or ``None`` if required is ``False``. + + Args: + arg: argument to convert + arg_name: argument name. + required: throws exception if ``True`` and argument provided is None + + Returns: + returns an ``int`` containing a timestamp (seconds from epoch) if conversion works + returns ``None`` if arg is ``None`` and required is set to ``False`` + otherwise throws an Exception + """ + if arg is None and required is True: + raise ValueError(f'Missing "{arg_name}"') + + if (isinstance(arg, str) and arg.isdigit()) or isinstance(arg, int | float): + # timestamp is a str containing digits - we just convert it to int + # or convert to int if the input is a float + return int(arg) + if isinstance(arg, str): + # we use dateparser to handle strings either in ISO8601 format, or + # relative time stamps. + # For example: format 2019-10-23T00:00:00 or "3 days", etc + date = dateparser.parse(arg, settings={"TIMEZONE": "UTC"}) + if date is None: + # if d is None it means dateparser failed to parse it + raise ValueError(f"Invalid date: {arg_name}") + + return int(date.timestamp()) + raise ValueError(f'Invalid date: "{arg_name}"') + + +def timezone_format(epoch: int) -> str: + """ + Converts an epoch timestamp into a formatted date in + a specific timezone defined in the integration parameter. + + Args: + epoch: argument to convert in epoch format + + Returns: + returns an ``str`` containing a formatted datestring in the timezone selected + """ + utc_datetime = datetime.utcfromtimestamp(epoch) + timezone = demisto.params().get("timezone", "UTC") + timezoneFormat = pytz.timezone(timezone) + format_datetime = utc_datetime.astimezone(timezoneFormat) + return format_datetime.strftime("%Y-%m-%dT%H:%M:%S") + + +def time_converter(time): + """ + Converts a given time string to a datetime object. + + Args: + time (str): The time string to be converted. + + Returns: + datetime: The converted datetime object. + + Raises: + ValueError: If the time string is in an invalid format. + """ + + # Regular expression patterns + iso_8601_pattern = re.compile( + r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$" + ) + unix_timestamp_pattern = re.compile(r"^\d+$") + + if iso_8601_pattern.match(time): + update_time = datetime.fromisoformat(time) + elif unix_timestamp_pattern.match(time): + update_time = datetime.fromtimestamp(int(time), pytz.utc) + else: + raise ValueError("Invalid time format") + + return update_time.strftime(DATE_FORMAT) + + +def convert_to_demisto_severity(severity: str) -> int: + """ + Maps Sekoia XDR urgency to Cortex XSOAR severity. + Converts the Sekoia XDR alert urgency level ('Low','Moderate','High','Major','Urgent') to Cortex XSOAR incident + severity (1 to 4). + + Args: + urgency (str): urgency display text as returned from the Sekoia XDR API. + + Returns: + int: Cortex XSOAR Severity (1 to 4) + """ + + return { + "Low": IncidentSeverity.LOW, + "Moderate": IncidentSeverity.MEDIUM, + "High": IncidentSeverity.HIGH, + "Major": IncidentSeverity.HIGH, + "Urgent": IncidentSeverity.CRITICAL, + }[severity] + + +def exclude_info_events(event_info: dict, exclude_info: str) -> list: + """ + Exclude information from the events. + This function will exclude information from the events that is duplicated or not needed. + + Args: + event_info (dict): JSON to be transformed removing some of the information. + exclude_info (str): the event fields to be removed from the results. + + Returns: + dict: JSON transformed with the information removed. + """ + splitted_exclude_info = exclude_info.split(",") + + """ Exclude headers from the readable output """ + headers = list(event_info["items"][0].keys()) + for header in splitted_exclude_info: + if header in headers: + headers.remove(header) + return headers + + +def undot(json_data: dict) -> str: + """ + Remove/Replace dots from the key names of a JSON. + This function transform the name of the JSON keys that contain "dots" to make it easier to reference them in XSOAR. + + Args: + json_data (dict): JSON to be transformed. + + Returns: + dict: JSON with the key names that contain "dots" transformed. + """ + replace_symbol = demisto.params().get("replace_dots_event", "_") + + if isinstance(json_data, str): + data = json.loads(json_data) + elif isinstance(json_data, dict): + data = json_data + else: + raise TypeError( + "JSON data sent to undot function must be a string or a dictionary" + ) + + # Iterate over each item in the items array + for item in data["items"]: + # Replace dots with underscores in each key + for key in list(item.keys()): + new_key = key.replace(".", replace_symbol) + if new_key != key: + item[new_key] = item.pop(key) + # Convert back to JSON and return it + return json.dumps(data) + + +def filter_list_by_keys(dicts_list: list, keys_to_keep: list) -> list: + """ + Filters a list of dictionaries by keeping only the specified keys. + + Args: + dicts_list (list): A list of dictionaries. + keys_to_keep (list): A list of keys to keep in the dictionaries. + + Returns: + list: A new list of dictionaries with only the specified keys. + """ + filtered_list = [] + for d in dicts_list: + filtered_dict = {key: value for key, value in d.items() if key in keys_to_keep} + filtered_list.append(filtered_dict) + return filtered_list + + +def filter_dict_by_keys(input_dict: dict, keys_to_keep: list) -> dict: + """ + Filters a dictionary by keeping only the key-value pairs whose keys are present in the given list. + + Args: + input_dict (dict): The dictionary to filter. + keys_to_keep (list): The list of keys to keep in the filtered dictionary. + + Returns: + dict: The filtered dictionary containing only the key-value pairs whose keys are present in the keys_to_keep list. + """ + return {key: value for key, value in input_dict.items() if key in keys_to_keep} + + +""" COMMAND FUNCTIONS """ + + +def fetch_incidents( + client: Client, + max_results: Optional[int], + last_run: Dict[str, int], + first_fetch_time: Optional[int], + alert_status: Optional[str], + alert_urgency: Optional[str], + alert_type: Optional[str], + fetch_mode: Optional[str], + fetch_with_assets: Optional[bool], + fetch_with_kill_chain: Optional[bool], +) -> Tuple[Dict[str, int], List[dict]]: + """ + This function retrieves new alerts every interval (default is 1 minute). + It has to implement the logic of making sure that incidents are fetched only onces and no incidents are missed. + By default it's invoked by XSOAR every minute. It will use last_run to save the timestamp of the last incident it + processed. If last_run is not provided, it should use the integration parameter first_fetch_time to determine when + to start fetching the first time. + + Args: + client (Client): Sekoia XDR client to use. + max_results (int): Maximum numbers of incidents per fetch. + last_run (dict): A dict with a key containing the latest incident created time we got from last fetch. + first_fetch_time(int): If last_run is None (first time we are fetching), it contains the timestamp in + milliseconds on when to start fetching incidents. + alert_status (str): status of the alert to search for. + alert_urgency (str): alert urgency range to search for. Format: "MIN_urgency,MAX_urgency". i.e: 80,100. + alert_type (str): type of alerts to search for. + fetch_mode (str): If the alert will be fetched with or without the events. + fetch_with_assets (bool): If the alert will include the assets information on the fetching. + fetch_with_kill_chain (bool): If the alert will include the kill chain information on the fetching. + Returns: + dict: Next run dictionary containing the timestamp that will be used in ``last_run`` on the next fetch. + list: List of incidents that will be created in XSOAR. + """ + # Get the last fetch time, if exists + # last_run is a dict with a single key, called last_fetch + last_fetch = last_run.get("last_fetch") + + # The case where no last_fetch or first_fetch_time are present. + if last_fetch is None and first_fetch_time is None: + raise DemistoException( + "Failure to fetch incidents. Can't find neither \ + last_fetch and first_fetch_time" + ) + # Handle first fetch time + elif last_fetch is None: + # if missing, use what provided via first_fetch_time + last_fetch = first_fetch_time + else: + # otherwise use the stored last fetch + last_fetch = int(last_fetch) + + # Convert time from epoch to ISO8601 in the correct format and add the ,now also + alerts_created_at = f"{time_converter(str(last_fetch))},now" + + # for type checking, making sure that latest_created_time is int + latest_created_time = cast(int, last_fetch) + + # Initialize an empty list of incidents to return + # Each incident is a dict with a string as a key + incidents: List[Dict[str, Any]] = [] + alerts = client.list_alerts( + alerts_limit=max_results, + alerts_status=alert_status, + alerts_created_at=alerts_created_at, + alerts_updated_at=None, + alerts_urgency=alert_urgency, + alerts_type=alert_type, + sort_by="created_at", + ) + + for alert in alerts["items"]: + # If no created_time set is as epoch (0). We use time in ms so we must + # convert it from the Sekoia XDR API response + incident_created_time = int(alert.get("created_at", "0")) + incident_created_time_ms = incident_created_time * 1000 + + # to prevent duplicates, we are only adding incidents with creation_time > last fetched incident + if last_fetch and incident_created_time <= last_fetch: + continue + + # If no name is present it will throw an exception + incident_name = alert["title"] + urgency = alert["urgency"] + + if fetch_mode == "Fetch With All Events": + # Add the events to the alert + earliest_time = alert["first_seen_at"] + lastest_time = "now" + term = f"alert_short_ids:{alert['short_id']}" + interval_in_seconds = INTERVAL_SECONDS_EVENTS + timeout_in_seconds = TIMEOUT_EVENTS + + # Add the events to the alert + args = { + "earliest_time": earliest_time, + "lastest_time": lastest_time, + "query": term, + "interval_in_seconds": interval_in_seconds, + "timeout_in_seconds": timeout_in_seconds, + } + events = search_events_command(args=args, client=client) + alert["events"] = events.outputs # pylint: disable=E1101 + + if fetch_with_assets: + # Add assets information to the alert + asset_list = [] + for asset in alert["assets"]: + try: + asset_info = client.get_asset(asset_uuid=asset) + asset_list.append(asset_info) + except Exception as e: + # Handle the exception if there is any problem with the API call + demisto.debug(f"Error fetching asset {asset}: {e}") + # Continue with the next asset + continue + alert["assets"] = asset_list + + if fetch_with_kill_chain and alert["kill_chain_short_id"]: + # Add kill chain information to the alert + try: + kill_chain = client.get_kill_chain( + kill_chain_uuid=alert["kill_chain_short_id"] + ) + alert["kill_chain"] = kill_chain + except Exception as e: + # Handle the exception if there is any problem with the API call + demisto.debug( + f"Error fetching kill chain information {kill_chain}: {e}" + ) + + # If the integration parameter is set to mirror add the instance name to be mapped to dbotMirrorInstance + incident = { + "name": incident_name, + "occurred": timestamp_to_datestring(incident_created_time_ms), + "severity": convert_to_demisto_severity(urgency.get("display", "Low")), + } + # If the integration parameter is set to mirror add the appropriate fields to the incident + alert["mirror_instance"] = demisto.integrationInstance() + incident["rawJSON"] = json.dumps(alert) + incidents.append(incident) + + # Update last run and add incident if the incident is newer than last fetch + if incident_created_time > latest_created_time: + latest_created_time = incident_created_time + + # Save the next_run as a dict with the last_fetch key to be stored + next_run = {"last_fetch": latest_created_time} + return next_run, incidents + + +def list_alerts_command(client: Client, args: Dict[str, Any]) -> CommandResults: + alerts = client.list_alerts( + alerts_limit=args.get("limit"), + alerts_status=args.get("status"), + alerts_created_at=args.get("created_at"), + alerts_updated_at=args.get("updated_at"), + alerts_urgency=args.get("urgency"), + alerts_type=args.get("alerts_type"), + sort_by=args.get("sort_by"), + ) + + header = ["title", "uuid", "short_id", "community_uuid"] + command_output = filter_list_by_keys(alerts["items"], header) + readable_output = tableToMarkdown("Alerts :", command_output, headers=header) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.ListAlerts", + outputs_key_field="short_id", + outputs=alerts["items"], + ) + + +def get_alert_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + alert_uuid = args["id"] + + alert = client.get_alert(alert_uuid=alert_uuid) + header = [ + "alert_type", + "short_id", + "created_by_type", + "kill_chain_short_id", + "details", + "rule", + ] + command_output = filter_dict_by_keys(alert, header) + readable_output = tableToMarkdown( + f"Alert {alert_uuid}:", command_output, headers=header + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Alert", + outputs_key_field="uuid", + outputs=alert, + ) + + +def query_events_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + earliest_time = args["earliest_time"] + lastest_time = args["lastest_time"] + term = args["query"] + max_last_events = args.get("max_last_events") + + jobQuery = client.query_events( + events_earliest_time=earliest_time, + events_latest_time=lastest_time, + events_term=term, + max_last_events=max_last_events, + ) + readable_output = tableToMarkdown( + f"Event search created using the term {term}:", jobQuery + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Events", + outputs_key_field="uuid", + outputs=jobQuery, + ) + + +def query_events_status_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + search_job_uuid = args["uuid"] + + status = client.query_events_status(event_search_job_uuid=search_job_uuid) + readable_output = tableToMarkdown(f"Status of the job {search_job_uuid}:", status) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Events", + outputs_key_field="search_job_uuid", + outputs=status, + ) + + +def retrieve_events_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + search_job_uuid = args["uuid"] + + events = client.retrieve_events(event_search_job_uuid=search_job_uuid) + readable_output = tableToMarkdown( + f"Events retrieved for the search {search_job_uuid}:", events + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Events", + outputs_key_field="search_job_uuid", + outputs=events, + ) + + +@polling_function(name="sekoia-xdr-search-events", requires_polling_arg=False) +def search_events_command(args: Dict[str, Any], client: Client) -> PollResult: + """Parameters""" + earliest_time = args["earliest_time"] + lastest_time = args["lastest_time"] + term = args["query"] + max_last_events = args.get("max_last_events") + exclude_info_arg = args.get("exclude_info") + exclude_info_param = demisto.params().get("exclude_info_events") + replace_symbol = demisto.params().get("replace_dots_event") + + if not (search_job_uuid := args.get("job_uuid")): + search = client.query_events( + events_earliest_time=earliest_time, + events_latest_time=lastest_time, + events_term=term, + max_last_events=max_last_events, + ) + search_job_uuid = search["uuid"] + + query_status = client.query_events_status(event_search_job_uuid=search_job_uuid) + finished_status = query_status["status"] == 2 + + if not finished_status: + return PollResult( + response=None, + continue_to_poll=True, + args_for_next_run=(args | {"job_uuid": search_job_uuid}), + partial_result=CommandResults( + readable_output=f"Query is still running. Current state: {query_status['status']}." + ), + ) + + events = client.retrieve_events(event_search_job_uuid=search_job_uuid) + total = max_last_events or events["total"] + + if len(events["items"]) > 0: + if exclude_info_arg: + headers = exclude_info_events( + event_info=events, exclude_info=exclude_info_arg + ) + headers = [header.replace(".", replace_symbol) for header in headers] + undot(json_data=events) + readable_output = tableToMarkdown( + f"{total} events out of {str(events['total'])} retrieved for the {term}", + events["items"], + headers=headers, + ) + elif exclude_info_param: + headers = exclude_info_events( + event_info=events, exclude_info=",".join(exclude_info_param) + ) + headers = [header.replace(".", replace_symbol) for header in headers] + undot(json_data=events) + readable_output = tableToMarkdown( + f"{total} events out of {events['total']} retrieved for the {term}", + events["items"], + headers=headers, + ) + else: + undot(json_data=events) + headers = list(events["items"][0].keys()) + readable_output = tableToMarkdown( + f"{total} events out of {events['total']} retrieved for the {term}", + events["items"], + headers=headers, + ) + else: + readable_output = tableToMarkdown( + f"{total} events out of {events['total']} retrieved for the {term}", + events["items"], + ) + + return PollResult( + response=CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Events.Results", + outputs_key_field="search_job_uuid", + outputs=events["items"], + ), + continue_to_poll=False, + ) + + +def update_status_alert_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + alert_uuid, updated_status, comment = ( + args["id"], + args["status"], + args.get("comment"), + ) + sekoia_transition = STATUS_TRANSITIONS.get(updated_status) + readable_output = "Unknown alert" + + workflow = client.get_workflow_alert(alert_uuid=alert_uuid) + + for action in workflow["actions"]: + if action["name"] == sekoia_transition: + update = client.update_status_alert( + alert_uuid=alert_uuid, action_uuid=action["id"], comment=comment + ) + if update or update == {}: + readable_output = ( + f"### Alert {alert_uuid} updated to status: {updated_status}" + ) + else: + raise DemistoException( + "Failure to update the status of the alert. \ + Run the command !sekoia-xdr-get-workflow-alert to see the possible\ + transitions and review the code." + ) + + return CommandResults(readable_output=readable_output, outputs=update) + + +def post_comment_alert_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + alert_uuid, comment, author = ( + args["id"], + args["comment"], + args.get("author"), + ) + + response = client.post_comment_alert( + alert_uuid=alert_uuid, content=comment, author=author + ) + response["date"] = timezone_format(response["date"]) + + readable_output = tableToMarkdown( + f"Alert {alert_uuid} updated with the comment: \n {comment}:", response + ) + + return CommandResults(readable_output=readable_output, outputs=response) + + +def get_comments_alert_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + alert_uuid = args["id"] + + response = client.get_comments_alert(alert_uuid=alert_uuid) + + for item in response["items"]: + # Add author of the comment + if item["author"].startswith("user"): + item["user"] = f"User with id {item['created_by']}" + elif item["author"].startswith("apikey"): + item["user"] = "Commented via API" + elif item["author"].startswith("application"): + item["user"] = "Sekoia.io" + else: + item["user"] = item["author"] + # Add formatted date of the comment + item["date"] = timezone_format(item["date"]) + + readable_output = tableToMarkdown( + f"Alert {alert_uuid} have the following comments:", response["items"] + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Comments", + outputs_key_field="alert_uuid", + outputs=response["items"], + ) + + +def get_workflow_alert_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + alert_uuid = args["id"] + + response = client.get_workflow_alert(alert_uuid=alert_uuid) + readable_output = tableToMarkdown( + f"Alert {alert_uuid} have the following available status transitions:", + response["actions"], + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.StatusTransitions", + outputs_key_field="alert_uuid", + outputs=response["actions"], + ) + + +def get_cases_alert_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + alert_uuid, case_id = args["alert_id"], args.get("case_id") + + response = client.get_cases_alert(alert_uuid=alert_uuid, case_id=case_id) + header = [ + "title", + "description", + "priority", + "short_id", + "status", + "community_uuid", + ] + command_output = filter_list_by_keys(response["items"], header) + readable_output = tableToMarkdown( + f"Alert {alert_uuid} have the following cases:", command_output, headers=header + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Cases", + outputs_key_field="alert_uuid", + outputs=response["items"], + ) + + +def get_asset_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + asset_uuid = args["asset_uuid"] + + asset = client.get_asset(asset_uuid=asset_uuid) + header = ["name", "uuid", "description"] + command_output = filter_dict_by_keys(asset, header) + readable_output = tableToMarkdown( + f"Asset {asset_uuid} have the following information:", + command_output, + headers=header, + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Asset", + outputs_key_field="uuid", + outputs=asset, + ) + + +def list_asset_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + limit, assets_type = args.get("limit"), args.get("assets_type") + + assets = client.list_asset(limit=limit, assets_type=assets_type) + header = ["name", "uuid", "description"] + command_output = filter_list_by_keys(assets["items"], header) + readable_output = tableToMarkdown( + f"List of {assets['total']} assets found:", command_output, headers=header + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.Assets", + outputs_key_field="asset_uuid", + outputs=assets["items"], + ) + + +def get_user_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + user_uuid = args["user_uuid"] + + user = client.get_user(user_uuid=user_uuid) + readable_output = tableToMarkdown( + f"User {user_uuid} have the following information:", user + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.User", + outputs_key_field="user_uuid", + outputs=user, + ) + + +def add_attributes_asset_command( + client: Client, args: Dict[str, Any] +) -> CommandResults: + """Parameters""" + asset_uuid, name, value = ( + args["asset_uuid"], + args["name"], + args["value"], + ) + + asset_attributes = client.add_attributes_asset( + asset_uuid=asset_uuid, name=name, value=value + ) + readable_output = tableToMarkdown( + f"Asset {asset_uuid} was updated with new attributes:", asset_attributes + ) + + return CommandResults( + readable_output=readable_output, + outputs_key_field="asset_uuid", + outputs=asset_attributes, + ) + + +def add_keys_asset_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + asset_uuid, name, value = ( + args["asset_uuid"], + args["name"], + args["value"], + ) + + asset_keys = client.add_keys_asset(asset_uuid=asset_uuid, name=name, value=value) + readable_output = tableToMarkdown( + f"Asset {asset_uuid} was updated with new keys:", asset_keys + ) + + return CommandResults( + readable_output=readable_output, + outputs_key_field="asset_uuid", + outputs=asset_keys, + ) + + +def remove_attribute_asset_command( + client: Client, args: Dict[str, Any] +) -> CommandResults: + """Parameters""" + asset_uuid, attribute_uuid = args["asset_uuid"], args["attribute_uuid"] + + client.remove_attribute_asset(asset_uuid=asset_uuid, attribute_uuid=attribute_uuid) + readable_output = ( + f"Asset {asset_uuid} had the following attribute removed:\n{attribute_uuid}" + ) + + return CommandResults(readable_output=readable_output) + + +def remove_key_asset_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + asset_uuid, key_uuid = args["asset_uuid"], args["key_uuid"] + + client.remove_key_asset(asset_uuid=asset_uuid, key_uuid=key_uuid) + readable_output = f"Asset {asset_uuid} had the following key removed:\n{key_uuid}" + + return CommandResults(readable_output=readable_output) + + +def get_kill_chain_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + kill_chain_uuid = args["kill_chain_uuid"] + + kill_chain = client.get_kill_chain(kill_chain_uuid=kill_chain_uuid) + readable_output = tableToMarkdown( + f"Kill chain {kill_chain_uuid} have the following information:", kill_chain + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.KillChain", + outputs_key_field="uuid", + outputs=kill_chain, + ) + + +def http_request_command(client: Client, args: Dict[str, Any]) -> CommandResults: + """Parameters""" + method, url_sufix, params = ( + args["method"], + args["url_sufix"], + args.get("parameters", {}), + ) + + request = client.http_request(method=method, params=params, url_suffix=url_sufix) + readable_output = tableToMarkdown( + f"The HTTP {method} request with params {params} returned the following information:", + request["items"] if request["items"] else request, + ) + + return CommandResults( + readable_output=readable_output, + outputs_prefix="SekoiaXDR.http_request", + outputs_key_field="uuid", + outputs=request, + ) + + +def test_module(client: Client) -> str: + """ + Tests API connectivity and authentication' + When 'ok' is returned it indicates the integration works like it is supposed to and connection to the service is successful. + Raises exceptions if something goes wrong. + + Args: + client (Client): Sekoia XDR client to use. + + Returns: + str: 'ok' if test passed, anything else will raise an exception and will fail the test. + """ + # Check a JWT token’s validity + # https://docs.sekoia.io/develop/rest_api/identity_and_authentication/#tag/User-Authentication/operation/get_validate_resource + + try: + client.get_validate_resource() + except DemistoException as e: + doc = """Please visit the API Key documentation for more information: + https://docs.sekoia.io/getting_started/generate_api_keys/""" + + if "T300" in str(e): + return f"Authorization Error: The token is invalid. {doc}" + elif "T301" in str(e): + return f"Authorization Error: The token has expired. {doc}" + elif "T302" in str(e): + return f"Authorization Error: The token has been revoked. {doc}" + else: + raise e + return "ok" + + +def main() -> None: + """ + main function, parses params and runs command functions + """ + + params, args, command = demisto.params(), demisto.args(), demisto.command() + + # get the service API url and api key + api_key = params.get("credentials", {}).get("password") + base_url = params.get("url") + + # if your Client class inherits from BaseClient, SSL verification is + # handled out of the box by it, just pass ``verify_certificate`` and ``proxy`` to + # the Client constructor + verify_certificate = not params.get("insecure", False) + proxy = params.get("proxy", False) + + # How much time before the first fetch to retrieve incidents + first_fetch_time = arg_to_datetime( + arg=params["first_fetch"], + arg_name="First fetch time", + required=True, + ) + first_fetch_timestamp = ( + int(first_fetch_time.timestamp()) if first_fetch_time else None + ) + + demisto.debug(f"Command being called is {command}") + try: + headers = {"Authorization": f"Bearer {api_key}"} + client = Client( + base_url=base_url, verify=verify_certificate, headers=headers, proxy=proxy + ) + + if command == "test-module": + # This is the call made when pressing the integration Test button. + result = test_module(client) + return_results(result) + + elif command == "fetch-incidents": + # Set and define the fetch incidents command to run after activated via integration settings. + alerts_status = ",".join(params.get("alerts_status", None)) + alerts_type = ",".join(params.get("alerts_type", None)) + alerts_urgency = params.get("alerts_urgency", None) + fetch_mode = params.get("fetch_mode") + fetch_with_assets = params.get("fetch_with_assets") + fetch_with_kill_chain = params.get("fetch_with_kill_chain") + + # Convert the argument to an int using helper function or set to MAX_INCIDENTS_TO_FETCH + max_results = arg_to_number(params["max_fetch"]) + last_run: Dict[ + str, Any + ] = demisto.getLastRun() # getLastRun() gets the last run dict + + next_run, incidents = fetch_incidents( + client=client, + max_results=max_results, + last_run=last_run, + first_fetch_time=first_fetch_timestamp, + alert_status=alerts_status, + alert_urgency=alerts_urgency, + alert_type=alerts_type, + fetch_mode=fetch_mode, + fetch_with_assets=fetch_with_assets, + fetch_with_kill_chain=fetch_with_kill_chain, + ) + + # saves next_run for the time fetch-incidents is invoked + demisto.setLastRun(next_run) + # fetch-incidents calls ``demisto.incidents()`` to provide the list of incidents to create + demisto.incidents(incidents) + + elif command == "sekoia-xdr-list-alerts": + return_results(list_alerts_command(client, args)) + elif command == "sekoia-xdr-get-alert": + return_results(get_alert_command(client, args)) + elif command == "sekoia-xdr-events-execute-query": + return_results(query_events_command(client, args)) + elif command == "sekoia-xdr-events-status-query": + return_results(query_events_status_command(client, args)) + elif command == "sekoia-xdr-events-results-query": + return_results(retrieve_events_command(client, args)) + elif command == "sekoia-xdr-search-events": + return_results(search_events_command(args, client)) + elif command == "sekoia-xdr-update-status-alert": + return_results(update_status_alert_command(client, args)) + elif command == "sekoia-xdr-post-comment-alert": + return_results(post_comment_alert_command(client, args)) + elif command == "sekoia-xdr-get-comments": + return_results(get_comments_alert_command(client, args)) + elif command == "sekoia-xdr-get-workflow-alert": + return_results(get_workflow_alert_command(client, args)) + elif command == "sekoia-xdr-get-cases-alert": + return_results(get_cases_alert_command(client, args)) + elif command == "sekoia-xdr-get-asset": + return_results(get_asset_command(client, args)) + elif command == "sekoia-xdr-list-assets": + return_results(list_asset_command(client, args)) + elif command == "sekoia-xdr-get-user": + return_results(get_user_command(client, args)) + elif command == "sekoia-xdr-add-attributes-asset": + return_results(add_attributes_asset_command(client, args)) + elif command == "sekoia-xdr-add-keys-asset": + return_results(add_keys_asset_command(client, args)) + elif command == "sekoia-xdr-remove-attribute-asset": + return_results(remove_attribute_asset_command(client, args)) + elif command == "sekoia-xdr-remove-key-asset": + return_results(remove_key_asset_command(client, args)) + elif command == "sekoia-xdr-get-kill-chain": + return_results(get_kill_chain_command(client, args)) + elif command == "sekoia-xdr-http-request": + return_results(http_request_command(client, args)) + else: + raise NotImplementedError(f"Command {command} is not implemented") + + # Log exceptions and return errors + except Exception as e: + return_error(f"Failed to execute {command} command.\nError:\n{str(e)}") + + +""" ENTRY POINT """ + +if __name__ in ("__main__", "__builtin__", "builtins"): + main() diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR.yml b/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR.yml new file mode 100644 index 000000000000..97f7da5c88e8 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR.yml @@ -0,0 +1,1122 @@ +commonfields: + id: Sekoia XDR + version: -1 +name: Sekoia XDR +display: Sekoia XDR +category: Analytics & SIEM +sectionOrder: +- Connect +- Collect +description: "Fetch alerts and events from SEKOIA.IO XDR.\nTo use this integration, please create an API Key with the appropriate permissions." +configuration: +- section: Connect + display: API key + displaypassword: API Key + name: credentials + type: 9 + required: true + hiddenusername: true +- section: Connect + display: Server URL (i.e. https://api.sekoia.io) + name: url + defaultvalue: https://api.sekoia.io + type: 0 + required: true +- section: Connect + advanced: true + display: Trust any certificate (not secure) + name: insecure + type: 8 + required: false +- section: Connect + advanced: true + display: Use system proxy settings + name: proxy + type: 8 + required: false +- section: Collect + display: Fetch incidents + name: isFetch + type: 8 + required: false +- section: Collect + display: Incident type + name: incidentType + type: 13 + required: false +- section: Collect + display: First fetch timestamp (

BlhLm)z^lNXn2Ew-2lRFUSN$z%d0xUW)OyZ zba{}c8Hn(7H2QD>78&rqIb!lD4SC{x;NQ35iNIopTW1bnJGmhRi*IU;%Eh9Ilw34S zm_|m>A&53<=s8#)M#3y$}Q_UC97ZhA(*GMNIrRM$d?>-t*l=&9w8e1H)NS&QW%AjRbOU9gZ);Z201 z|KAnu3+5SQER8I8FuZ#SD?(n#oOsn6wU@Sb{(5k-7cyRY{GB(S-7+i*79xL4zp)@g zQQepE99VzQ8~fuE_=eCMGrtBT793mekLr4v7{CJc{qZry?L$!3A2&QmQLgfI*4DO9 zP{3<7uC`X)m}kYjJ{QL)vcV!K)8vl>J&GX@A%w)^V|U@TMNdw7g?N)+TNDdZr6bxM zQ|=LkvXtH=fa}TR{=vB3s3Fv+@jcUiD6BWO+GTusZKL7n5YYJnnRj*%&K;;wG8=l) z{HWBzl=yZB;%t|#cj(`5XpAp4#^*X?SxSL(Hq+6{Ky+%2+NmzYXKUM^L=un7O9ErL zmggYgVmP`x)$gsZ|78z?@Um=e`TCqKoU++O(Md6O^YL&d2?e+s_;-gTzt8ZT2C%Oy zgj{c9TNLq)YGiy1x{}Tk?rUXMhxYVHchNiPILKwUto_la0u@i)O*Xz%xY2x$y}IiT z!|*EQhdV_x*%C6smF}J93UNbMy@Uh8iEaU0b`X=dxwU=a@X3i#QxtxbLMBCa{V@vN1sb+tzIIXy69AUHWo zgvg1N?)vI$^-j7jXccWRyE&Z)yYqqn;czgz-y=TcWiVAnfyastS>a`VZ8YBF+Hx?u zdrslwH08foE?_Djb>Xtx)_-SZavf(sgkXdBgRYN2Q%XmOw~Hv2Onf!rA&NIlllPhT zJ5M(|mp4GTp1vqp0C7Slq1+t16y=5=$^AqRZx(%vH z^M25ECj>dC7t?6YQ>^^6@P0lH?@v@n;r&SHYMx0Ua?xS1sV^KBL&l{SH9=Sa^m{j^ z-JJO2JxC{hPQIeq{gAe5?i5;_53H|$zgMmPX*1s|rNzf_k(Esf(gqAjHF}TZ5{*EjOFJ4)wS% zQbA&J=t1sxhmw~c%_|d`t11eQvd_#W1t3_st?V>$llLSja5Je%NOAp9ao4Zfs9jUn zDh?s&u~#dqB8cRM_WcT$gkvDsgQXzmj@OljzW>HF1`853*33yLQnxlk95zXLjve7r z(z1OJ-+P`CmUO+6Pbt`I%<{zJytV5JigUbREX*(Jn!^fwCCms|Eb!3$=0k7mM|2AFlIWRG5q~Ia@=y+PEmQ(XbZJjc zmuc-f(PC5W3kCjhv57*92Y6Penm9j3cE?a|LbN{GsBAWy#!44mqg&&H4|(_zI&V#N zBWJ_9b=6&`83-pyo>&lT^=)I5gzI>jw8bAY|FjYEIDCI1GzDV?SF|4=?;rGJ(m~f) z0nQ-M6iJGF52`cDu{9$eSuu~dt@Kad4$t;Jx2h4F0d z)rGP)HJ9AP8@V=!vQvFSxVGf-V_qlAeDn#Fz29B20+Qmt%kvZ{9vlaol!R*ubf z49)v&dKL%ahOM94tZEx;974SEORFO9l1a{>}b&}Pu(L;e&Due z*?f7jBRz&_&6~&jF!iTN*r_xsg-OtNxtw4Ml^!d7hNpl%mAFPNQ@2xen6J|-;+wwn z7B#0hIi(OFyJg&R#=vRnYsuJm)U1y!i>zW9En5`%*qgUJi`61i2h))rTWn8WXl@5q z1T8_4C~Li0tOgkY%Qr3nlbSKA^~Rr8@fL(B`{eQiEWRq-{Eg}KAH7QT4?mIb{wrUT zkja8^uTpvOnSXrz zz2{bbM}q#>LK!Cumgrnk_o_`q8tVS4UJ13BkJ2JazVZ@=+;#Ev`>LVA1w38$^w(W@ zY;>|>D84CiqejF2s$L1Tm=Bycpy=NT%YqNU`Ha;5H|g7Au7DM|Mx&&tUH1NznSr>a zY`kr)_LsrJ0#?Wr@Q!SmrH2#AKMlj~A`J)&3kwSi3kwSi3kwSi3k!=?;(t|x>PRM| RfiwUB002ovPDHLkV1lE@B1r%M literal 0 HcmV?d00001 diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR_test.py b/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR_test.py new file mode 100644 index 000000000000..c29f2739682e --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/SekoiaXDR_test.py @@ -0,0 +1,549 @@ +from CommonServerPython import * + +import SekoiaXDR # type: ignore + +from datetime import datetime +import pytest +import json + + +MOCK_URL = "https://api.sekoia.io" + + +def util_load_json(path): + with open(path, encoding="utf-8") as f: + return json.loads(f.read()) + + +@pytest.fixture(scope="session") +def client(): + api_key = "test_api_key" + headers = {"Authorization": f"Bearer {api_key}"} + client = SekoiaXDR.Client( + base_url=MOCK_URL, + headers=headers, + ) + return client + + +""" TEST HELPER FUNCTIONS """ + + +def test_arg_to_timestamp(): + assert ( + SekoiaXDR.arg_to_timestamp("2024-04-25T09:20:55", "lastupdate", True) + == 1714036855 + ) + assert SekoiaXDR.arg_to_timestamp(1714036855.55, "lastupdate", True) == 1714036855 + + three_days_ago = datetime.now() - timedelta(days=3) + assert SekoiaXDR.arg_to_timestamp("3 days", "lastupdate", True) == int( + three_days_ago.timestamp() + ) + + with pytest.raises(ValueError): + assert SekoiaXDR.arg_to_timestamp(None, "lastupdate", True) == 1714036855 + + +def test_timezone_format(): + assert SekoiaXDR.timezone_format(1714036855) == "2024-04-25T09:20:55" + assert SekoiaXDR.timezone_format(1710494455) == "2024-03-15T09:20:55" + assert SekoiaXDR.timezone_format(1678872055) == "2023-03-15T09:20:55" + + +def test_time_converter(): + assert ( + SekoiaXDR.time_converter("2024-04-20T15:30:00+00:00") == "2024-04-20T15:30:00" + ) + assert SekoiaXDR.time_converter("1678872055") == "2023-03-15T09:20:55" + with pytest.raises(ValueError): + assert SekoiaXDR.time_converter("2024-04-20T15:30:00") == "2024-04-20T15:30:00" + + +def test_convert_to_demisto_severity(): + assert SekoiaXDR.convert_to_demisto_severity("Low") == 1 + assert SekoiaXDR.convert_to_demisto_severity("Moderate") == 2 + assert SekoiaXDR.convert_to_demisto_severity("High") == 3 + assert SekoiaXDR.convert_to_demisto_severity("Major") == 3 + assert SekoiaXDR.convert_to_demisto_severity("Urgent") == 4 + + +def test_exclude_info_events(): + upload_test_data = util_load_json("test_data/SekoiaXDR_retrieve_events.json") + + result = SekoiaXDR.exclude_info_events(upload_test_data, "sekoiaio.any_asset.name") + assert "sekoiaio.any_asset.name" not in result + + second_result = SekoiaXDR.exclude_info_events( + upload_test_data, "sekoiaio.tags.related.ip,sekoiaio.tags.host.ip" + ) + assert "sekoiaio.tags.related.ip" not in second_result + assert "sekoiaio.tags.host.ip" not in second_result + + +def test_undot(): + upload_test_data = util_load_json("test_data/SekoiaXDR_retrieve_events.json") + result = SekoiaXDR.undot(upload_test_data) + + assert "agent_id" in result + assert "agent.id" not in result + + +def test_filter_list_by_keys(): + dicts_list = [ + {"key1": "value1", "key2": "value2", "key3": "value3"}, + {"key1": "value4", "key2": "value5", "key3": "value6"}, + {"key1": "value7", "key2": "value8", "key3": "value9"}, + ] + keys_to_keep = ["key1", "key3"] + expected_result = [ + {"key1": "value1", "key3": "value3"}, + {"key1": "value4", "key3": "value6"}, + {"key1": "value7", "key3": "value9"}, + ] + assert SekoiaXDR.filter_list_by_keys(dicts_list, keys_to_keep) == expected_result + + +def test_filter_list_by_keys_with_empty_list(): + dicts_list = [] + keys_to_keep = ["key1", "key3"] + expected_result = [] + assert SekoiaXDR.filter_list_by_keys(dicts_list, keys_to_keep) == expected_result + + +def test_filter_dict_by_keys(): + dict = { + "key1": "value1", + "key2": "value2", + "key3": "value3", + } + keys_to_keep = ["key1", "key3"] + expected_result = { + "key1": "value1", + "key3": "value3", + } + assert SekoiaXDR.filter_dict_by_keys(dict, keys_to_keep) == expected_result + + +def test_filter_dict_by_keys_with_empty_dict(): + dict = {} + keys_to_keep = ["key1", "key3"] + expected_result = {} + assert SekoiaXDR.filter_dict_by_keys(dict, keys_to_keep) == expected_result + + +""" TEST COMMANDS FUNCTIONS """ + + +def test_test_module_ok(client, requests_mock): + response = { + "csrf": "aaa", + "fresh": False, + "iat": 123456, + "identity": "apikey:123456", + "jti": "123456", + "nbf": 123456, + "type": "access", + "user_claims": None, + } + + requests_mock.get(MOCK_URL + "/v1/auth/validate", json=response) + assert SekoiaXDR.test_module(client) == "ok" + + +@pytest.mark.parametrize( + "api_response, expected", + [ + ({"message": "The token is invalid", "code": "T300"}, "The token is invalid."), + ( + {"message": "The token has expired", "code": "T301"}, + "The token has expired.", + ), + ({"message": "Token revoked", "code": "T302"}, "The token has been revoked."), + ], +) +def test_test_module_nok(client, requests_mock, api_response, expected): + requests_mock.get( + MOCK_URL + "/v1/auth/validate", json=api_response, status_code=401 + ) + + assert expected in SekoiaXDR.test_module(client) + + +@pytest.mark.parametrize( + "method, url_suffix, params, json_test_file", + [ + ("GET", "/v1/sic/alerts", {}, "test_data/SekoiaXDR_get_alerts.json"), + ( + "GET", + "/v1/asset-management/assets", + {}, + "test_data/SekoiaXDR_get_assets.json", + ), + ], +) +def test_http_request_list( + client, requests_mock, method, url_suffix, params, json_test_file +): + mock_response = util_load_json(json_test_file) + requests_mock.get(MOCK_URL + url_suffix, json=mock_response) + + args = {"url_sufix": url_suffix, "method": method, "params": params} + result = SekoiaXDR.http_request_command(client=client, args=args) + + assert result.outputs["items"] == mock_response["items"] + + +def test_list_alerts(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_get_alerts.json") + requests_mock.get(MOCK_URL + "/v1/sic/alerts", json=mock_response) + + args = {} + result = SekoiaXDR.list_alerts_command(client=client, args=args) + + assert result.outputs == mock_response["items"] + + +def test_get_alert(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_get_alert.json") + requests_mock.get(MOCK_URL + "/v1/sic/alerts/ALL1A4SKUiU2", json=mock_response) + + args = {"id": "ALL1A4SKUiU2"} + result = SekoiaXDR.get_alert_command(client=client, args=args) + + assert result.outputs == mock_response + + +def test_get_workflow_alert(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_get_alert_workflow.json") + requests_mock.get( + MOCK_URL + "/v1/sic/alerts/ALWVYiP2Msz4/workflow", json=mock_response + ) + + args = {"id": "ALWVYiP2Msz4"} + result = SekoiaXDR.get_workflow_alert_command(client=client, args=args) + + assert len(result.outputs) == len(mock_response["actions"]) + + +def test_get_cases_alert(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_get_alert_cases.json") + requests_mock.get( + MOCK_URL + + "/v1/sic/cases?match[alert_uuid]=4fb686e0-ab0c-479c-9afe-856beef9d592&match[short_id]=CAs3AT1XeGCp", + json=mock_response, + ) + + args = { + "alert_id": "4fb686e0-ab0c-479c-9afe-856beef9d592", + "case_id": "CAs3AT1XeGCp", + } + result = SekoiaXDR.get_cases_alert_command(client=client, args=args) + + assert len(result.outputs) > 0 + + +def test_update_status_alert(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_get_alert_workflow.json") + requests_mock.get( + MOCK_URL + "/v1/sic/alerts/ALWVYiP2Msz4/workflow", json=mock_response + ) + requests_mock.patch(MOCK_URL + "/v1/sic/alerts/ALWVYiP2Msz4/workflow", json={}) + + args = {"id": "ALWVYiP2Msz4", "status": "Acknowledged", "comment": "test cortex"} + result = SekoiaXDR.update_status_alert_command(client=client, args=args) + + assert result.outputs == {} + + +def test_comments_alert_command(client, requests_mock): + mock_response_alert_comments = util_load_json( + "test_data/SekoiaXDR_get_alert_comments.json" + ) + requests_mock.get( + MOCK_URL + "/v1/sic/alerts/ALL1A4SKUiU2/comments", + json=mock_response_alert_comments, + ) + + args = {"id": "ALL1A4SKUiU2"} + result = SekoiaXDR.get_comments_alert_command(client=client, args=args) + + for item in result.outputs: + if item["author"].startswith("user"): + assert item["user"] == "User with id 7114c307-d86c-4c55" + if item["author"].startswith("apikey"): + assert item["user"] == "Commented via API" + if item["author"].startswith("application"): + assert item["user"] == "Sekoia.io" + + +def test_post_comment_alert(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_post_alert_comment.json") + requests_mock.post( + MOCK_URL + "/v1/sic/alerts/ALU9FpFZoApW/comments", json=mock_response + ) + + args = { + "id": "ALU9FpFZoApW", + "comment": "This alert is always on ongoing status", + "author": "Joe", + } + result = SekoiaXDR.post_comment_alert_command(client=client, args=args) + assert result.outputs["author"] == args["author"] + assert result.outputs["content"] == args["comment"] + + +def kill_chain_command(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_get_killchain.json") + requests_mock.get( + MOCK_URL + "/v1/sic/kill-chains/73708d4f-419f-44aa", json=mock_response + ) + + args = {"kill_chain_uuid": "73708d4f-419f-44aa"} + result = SekoiaXDR.get_kill_chain_command(client=client, args=args) + assert result.outputs["uuid"] == args["73708d4f-419f-44aa"] + + +def test_query_events(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_query_events.json") + requests_mock.post(MOCK_URL + "/v1/sic/conf/events/search/jobs", json=mock_response) + + args = { + "query": "sekoiaio.intake.uuid:834a2d7f-3623-4b26", + "earliest_time": "2024-04-25T10:00:23", + "lastest_time": "2024-04-25T15:00:23", + } + result = SekoiaXDR.query_events_command(client=client, args=args) + + assert result.outputs == mock_response + + +def test_query_events_status(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_query_events_status.json") + requests_mock.get( + MOCK_URL + "/v1/sic/conf/events/search/jobs/df904d2e-2c57-488f", + json=mock_response, + ) + + args = {"uuid": "df904d2e-2c57-488f"} + result = SekoiaXDR.query_events_status_command(client=client, args=args) + + assert result.outputs == mock_response + + +def test_retrieve_events(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_retrieve_events.json") + requests_mock.get( + MOCK_URL + "/v1/sic/conf/events/search/jobs/df904d2e-2c57-488f/events", + json=mock_response, + ) + + args = {"uuid": "df904d2e-2c57-488f"} + result = SekoiaXDR.retrieve_events_command(client=client, args=args) + + assert result.outputs == mock_response + + +def test_search_events(client, requests_mock, mocker): + mock_response_query_events = util_load_json("test_data/SekoiaXDR_query_events.json") + mock_response_query_events_status = util_load_json( + "test_data/SekoiaXDR_query_events_status.json" + ) + mock_response_retrieve_events = util_load_json( + "test_data/SekoiaXDR_retrieve_events.json" + ) + requests_mock.post( + MOCK_URL + "/v1/sic/conf/events/search/jobs", json=mock_response_query_events + ) + requests_mock.get( + MOCK_URL + "/v1/sic/conf/events/search/jobs/df904d2e-2c57-488f", + json=mock_response_query_events_status, + ) + requests_mock.get( + MOCK_URL + "/v1/sic/conf/events/search/jobs/df904d2e-2c57-488f/events", + json=mock_response_retrieve_events, + ) + + params = {"exclude_info_events": "False", "replace_dots_event": "_"} + mocker.patch.object(demisto, "params", return_value=params) + args = { + "earliest_time": "2024-04-25T10:00:23", + "lastest_time": "2024-04-25T15:00:23", + "query": "sekoiaio.intake.uuid:834a2d7f-3623-4b26", + "max_last_events": "100", + "timeout_in_seconds": "5", + "exclude_info": "False", + "interval_in_seconds": "3", + } + result: PollResult = SekoiaXDR.search_events_command(client=client, args=args) + + assert result.outputs[0]["action_id"] # type: ignore + assert result.outputs[0]["action_outcome"] # type: ignore + assert result.outputs[0]["action_name"] # type: ignore + + +def test_list_assets(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_list_assets.json") + requests_mock.get( + MOCK_URL + "/v1/asset-management/assets?limit=5&match[type_name]=computer", + json=mock_response, + ) + + args = {"limit": "5", "assets_type": "computer"} + result = SekoiaXDR.list_asset_command(client=client, args=args) + + assert len(result.outputs) == 2 + + +def test_get_asset(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_get_asset.json") + requests_mock.get( + MOCK_URL + "/v1/asset-management/assets/015ea33b-a7a2-4e34", json=mock_response + ) + + args = {"asset_uuid": "015ea33b-a7a2-4e34"} + result = SekoiaXDR.get_asset_command(client=client, args=args) + + assert result.outputs["uuid"] == args["asset_uuid"] + + +def test_add_keys_asset(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_post_asset_key.json") + requests_mock.post( + MOCK_URL + + "/v1/asset-management/assets/015ea33b-a7a2-4e34-8beb-0197a93a1011/keys?name=host&value=computer1", + json=mock_response, + ) + + args = { + "asset_uuid": "015ea33b-a7a2-4e34-8beb-0197a93a1011", + "name": "host", + "value": "computer1", + } + result = SekoiaXDR.add_keys_asset_command(client=client, args=args) + + assert result.outputs["name"] == args["name"] + assert result.outputs["value"] == args["value"] + + +def test_remove_keys_asset(client, requests_mock): + requests_mock.delete( + MOCK_URL + + "/v1/asset-management/assets/015ea33b-a7a2-4e34-8beb-0197a93a1011/keys/8007222c-f135-4f5f", + json={}, + ) + + args = { + "asset_uuid": "015ea33b-a7a2-4e34-8beb-0197a93a1011", + "key_uuid": "8007222c-f135-4f5f", + } + result = SekoiaXDR.remove_key_asset_command(client=client, args=args) + + assert not result.outputs + + +def test_add_attr_asset(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_post_asset_attr.json") + requests_mock.post( + MOCK_URL + + "/v1/asset-management/assets/015ea33b-a7a2-4e34-8beb-0197a93a1011/attr?name=attr_test_4&value=value4", + json=mock_response, + ) + + args = { + "asset_uuid": "015ea33b-a7a2-4e34-8beb-0197a93a1011", + "name": "attr_test_4", + "value": "value4", + } + result = SekoiaXDR.add_attributes_asset_command(client=client, args=args) + + assert result.outputs["name"] == args["name"] + assert result.outputs["value"] == args["value"] + + +def test_remove_attr_asset(client, requests_mock): + requests_mock.delete( + MOCK_URL + + "/v1/asset-management/assets/015ea33b-a7a2-4e34-8beb-0197a93a1011/attr/8007222c-f135-4f5f", + json={}, + ) + + args = { + "asset_uuid": "015ea33b-a7a2-4e34-8beb-0197a93a1011", + "attribute_uuid": "8007222c-f135-4f5f", + } + result = SekoiaXDR.remove_attribute_asset_command(client=client, args=args) + + assert not result.outputs + + +def test_get_user(client, requests_mock): + mock_response = util_load_json("test_data/SekoiaXDR_get_user.json") + requests_mock.get(MOCK_URL + "/v1/users/7114c307-d86c-4c55", json=mock_response) + + args = {"user_uuid": "7114c307-d86c-4c55"} + result = SekoiaXDR.get_user_command(client=client, args=args) + + assert result.outputs["firstname"] == "Joe" + assert result.outputs["lastname"] == "done" + + +@pytest.mark.parametrize( + "max_results, last_run, first_fetch_time, alert_status, alert_urgency, alert_type, fetch_mode, \ + fetch_with_assets, fetch_with_kill_chain", + [ + ( + 100, + {"last_fetch": 1574065501}, + None, + None, + None, + None, + None, + None, + None, + ), + ( + 100, + {"last_fetch": None}, + 1574065501, + None, + None, + None, + None, + None, + None, + ), + ], +) +def test_fetch_incidents( + client, + requests_mock, + max_results, + last_run, + first_fetch_time, + alert_status, + alert_urgency, + alert_type, + fetch_mode, + fetch_with_assets, + fetch_with_kill_chain, +): + mock_response = util_load_json("test_data/SekoiaXDR_get_alerts.json") + requests_mock.get(MOCK_URL + "/v1/sic/alerts", json=mock_response) + + results = SekoiaXDR.fetch_incidents( + client, + max_results, + last_run, + first_fetch_time, + alert_status, + alert_urgency, + alert_type, + fetch_mode, + fetch_with_assets, + fetch_with_kill_chain, + ) + + assert results[0]["last_fetch"] + assert len(results[1]) == 2 diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/command_example.txt b/Packs/SekoiaXDR/Integrations/SekoiaXDR/command_example.txt new file mode 100644 index 000000000000..a09921ca604b --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/command_example.txt @@ -0,0 +1,19 @@ +!sekoia-xdr-list-assets limit=5 assets_type="computer" +!sekoia-xdr-get-asset asset_uuid="e553efc7-ab91-48f6-8c79-efd18ada9916" +!sekoia-xdr-add-attributes-asset asset_uuid="e553efc7-ab91-48f6-8c79-efd18ada9916" name="Test" value="Test2" +!sekoia-xdr-remove-attribute-asset asset_uuid=e553efc7-ab91-48f6-8c79-efd18ada9916 attribute_uuid=95733049-4ffb-434e-9036-742a01871fc4 +!sekoia-xdr-add-keys-asset asset_uuid=e553efc7-ab91-48f6-8c79-efd18ada9916 name="MyKey" value="MyValue" +!sekoia-xdr-remove-key-asset key_uuid=32dc9f1d-0e7b-4550-a042-eeb52c4a537e asset_uuid=e553efc7-ab91-48f6-8c79-efd18ada9916 +!sekoia-xdr-events-execute-query earliest_time=-1d lastest_time=+1d query=alert_short_ids:ALUnyZCYZ9Ga +!sekoia-xdr-events-status-query uuid=127@cd3435a4-5937-46ed-8163-ffdd5e7ab95b +!sekoia-xdr-events-results-query uuid=127@cd3435a4-5937-46ed-8163-ffdd5e7ab95b +!sekoia-xdr-search-events earliest_time=-1d lastest_time=+1d query=alert_short_ids:ALVDPAcN6MYo +!sekoia-xdr-list-alerts limit="5" sort_by="created_at" +!sekoia-xdr-get-alert id=AL3qRBWfoveP +!sekoia-xdr-get-workflow-alert id=AL3qRBWfoveP +!sekoia-xdr-update-status-alert id=50314bd2-5493-4518-a242-71d405877e22 +!sekoia-xdr-get-cases-alert +!sekoia-xdr-get-kill-chain kill_chain_uuid=KCYDJkEpzMot +!sekoia-xdr-get-comments id=d444aa87-1408-49d0-9946-86bbc8d740f3 +!sekoia-xdr-get-user user_uuid=b57d2513-7037-4fe3-b1f7-9126e52dcc32 +!sekoia-xdr-http-request method=GET url_sufix=/sic/alerts/ diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert.json new file mode 100644 index 000000000000..5736ce565d78 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert.json @@ -0,0 +1,356 @@ +{ + "uuid": "80ee2ccc-11e3-4416", + "title": "Feed Enriched", + "created_at": 1574343159, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "updated_at": 1687958505, + "updated_by": "59899459-d385-48da", + "updated_by_type": "application", + "community_uuid": "52bd045f-4199-4361", + "short_id": "ALL1A4SKUiU2", + "entity": { + "uuid": "7f7676e7-a254-43c3", + "name": "Information Technology test" + }, + "urgency": { + "current_value": 20, + "value": 20, + "severity": 40, + "criticity": 0, + "display": "Moderate" + }, + "alert_type": { + "value": "brute-force", + "category": "intrusion-attempts" + }, + "status": { + "uuid": "8f206505-af6d-433e", + "name": "Acknowledged", + "description": "The alert was checked by an operator" + }, + "rule": { + "uuid": "ebcb5113-dcd1-4563", + "name": "Feed Enriched", + "description": "description test", + "severity": 40, + "type": null, + "pattern": "[ipv4-addr:value = '1.2.3.4']" + }, + "detection_type": null, + "source": "1.2.3.4", + "target": null, + "similar": 11, + "details": "details description", + "ttps": [], + "adversaries": [], + "stix": {}, + "kill_chain_short_id": "KCXKNfnJuUUU", + "number_of_unseen_comments": 0, + "first_seen_at": "2019-11-21T13:32:39.839600Z", + "last_seen_at": null, + "assets": [], + "time_to_detect": null, + "time_to_acknowledge": 113615345, + "time_to_respond": null, + "time_to_resolve": 111893849, + "comments": [ + { + "uuid": "40528f74-2523-428f", + "content": "Alert has been closed automatically because it is older than 2 weeks.", + "author": "apikey:f93a35e0-b9aa-4c00", + "date": 1686237010, + "created_by": "f93a35e0-b9aa-4c95", + "created_by_type": "apikey", + "unseen": false + } + ], + "history": [ + { + "uuid": "be86c882-7ca2-4d23", + "created_at": 1713431780, + "created_by": "f870d496-a37b-4aec", + "created_by_type": "apikey", + "entry_type": "comment", + "comment": { + "uuid": "5661ca10-33cf-4b49", + "status": "created", + "display_name": "apikey:f870d496-a37b-4aec", + "content": "Alert has been closed automatically" + }, + "history_comments": [] + }, + { + "uuid": "bcf71278-6dd4-41b7", + "created_at": 1687958505, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "entry_type": "alert", + "alert": { + "status": "Acknowledged", + "previous_status": "Closed" + }, + "history_comments": [] + }, + { + "uuid": "792d6585-61b3-4da4", + "created_at": 1686237009, + "created_by": "f93a35e0-b9aa-4c95", + "created_by_type": "apikey", + "entry_type": "alert", + "alert": { + "status": "Closed", + "previous_status": "Pending" + }, + "history_comments": [ + { + "uuid": "40528f74-2523-428f-adb9-b1b3da5b3bcc", + "content": "Alert has been closed automatically because it is older than 2 weeks.", + "author": "apikey:f93a35e0-b9aa-4c95-ab31-40f1e9aea5a4", + "date": 1686237010, + "created_by": "f93a35e0-b9aa-4c95-ab31-40f1e9aea5a4", + "created_by_type": "apikey" + } + ] + }, + { + "uuid": "400e4f8f-9473-41c0", + "created_at": 1574343164, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "entry_type": "alert", + "alert": { + "status": "Pending", + "previous_status": null + }, + "history_comments": [] + }, + { + "uuid": "94589f34-9c01-4592", + "created_at": 1574343159, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "entry_type": "countermeasure_action_step", + "countermeasure": { + "uuid": "43caf7af-06ff-4821", + "status": "created" + }, + "history_comments": [], + "countermeasure_action_step": { + "status": "created", + "name": "1" + } + }, + { + "uuid": "f143ebf4-d3e1-4930", + "created_at": 1574343159, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "entry_type": "countermeasure", + "countermeasure": { + "uuid": "9f2a40ae-add5-49f8", + "status": "created" + }, + "history_comments": [] + }, + { + "uuid": "b77f2a3e-fd30-43be", + "created_at": 1574343159, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "entry_type": "countermeasure_action_step", + "countermeasure": { + "uuid": "9f2a40ae-add5-49f8", + "status": "created" + }, + "history_comments": [], + "countermeasure_action_step": { + "status": "created", + "name": "3" + } + }, + { + "uuid": "8c22657d-4d55-4842", + "created_at": 1574343159, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "entry_type": "countermeasure", + "countermeasure": { + "uuid": "43caf7af-06ff-4821", + "status": "created" + }, + "history_comments": [] + } + ], + "countermeasures": [ + { + "uuid": "43caf7af-06ff-4821-9770-2023c16153f7", + "model_uuid": "55117974-f59e-46df", + "relevance": 50, + "dynamic_relevance": 0, + "duration": null, + "status": "created", + "created_at": "2019-11-21T13:32:39.839600Z", + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "activated_at": null, + "activated_by": null, + "activated_by_type": null, + "denied_at": null, + "denied_by": null, + "denied_by_type": null, + "course_of_action": { + "id": "course-of-action--43caf7af-06ff", + "type": "course-of-action", + "created_by_ref": "identity--59899459-d385", + "created": "2019-11-21T13:32:39.839600+00:00", + "name": "countermeasure--55117974-f59e", + "description": "Report the issue to security team", + "action-steps": [ + { + "name": "1", + "description": "Notify the security team", + "type": "openc2", + "object": { + "action": "investigate", + "target": { + "uri": "$ALERT_URI" + } + } + } + ], + "x_sic_countermeasure": { + "relevance": 50, + "dynamic_relevance": 0, + "uuid": "55117974-f59e-46df" + }, + "modified": "2019-11-21T13:32:39.839600+00:00" + }, + "action_steps": [ + { + "uuid": "1aacb24b-7ec6-41c5", + "name": "1", + "description": "Notify the security team", + "status": "created", + "created_at": "2019-11-21T13:32:39.839600Z", + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "activated_at": null, + "activated_by": null, + "activated_by_type": null, + "denied_at": null, + "denied_by": null, + "denied_by_type": null, + "action_order": 0, + "object": { + "action": "investigate", + "target": { + "uri": "$ALERT_URI" + } + }, + "comments": [], + "assignee": null, + "type": null + } + ], + "name": "countermeasure--55117974-f59e", + "description": "Report the issue to security team", + "comments": [], + "assignee": null, + "type": "openc2", + "external_ref": null, + "alert_uuid": "80ee2ccc-11e3-4416" + }, + { + "uuid": "9f2a40ae-add5-49f8", + "model_uuid": "7d2bb069-b3ff-40ca", + "relevance": 76, + "dynamic_relevance": 0, + "duration": null, + "status": "created", + "created_at": "2019-11-21T13:32:39.839600Z", + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "activated_at": null, + "activated_by": null, + "activated_by_type": null, + "denied_at": null, + "denied_by": null, + "denied_by_type": null, + "course_of_action": { + "id": "course-of-action--9f2a40ae-add5", + "type": "course-of-action", + "created_by_ref": "identity--59899459-d385a", + "created": "2019-11-21T13:32:39.839600+00:00", + "name": "countermeasure--7d2bb069-b3ff", + "description": "Temporarily block the concerned system", + "action-steps": [ + { + "name": "3", + "description": "Block the IP address temporarily", + "type": "openc2", + "object": { + "action": "deny", + "target": { + "ipv4_net": "1.2.3.4" + }, + "actuator": { + "slpf": {} + }, + "args": { + "duration": 7800000000 + } + } + } + ], + "x_sic_countermeasure": { + "relevance": 76, + "dynamic_relevance": 0, + "uuid": "7d2bb069-b3ff-40ca" + }, + "modified": "2019-11-21T13:32:39.839600+00:00" + }, + "action_steps": [ + { + "uuid": "905e5315-a3a9-4efd", + "name": "3", + "description": "Block the IP address temporarily", + "status": "created", + "created_at": "2019-11-21T13:32:39.839600Z", + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "activated_at": null, + "activated_by": null, + "activated_by_type": null, + "denied_at": null, + "denied_by": null, + "denied_by_type": null, + "action_order": 0, + "object": { + "action": "deny", + "target": { + "ipv4_net": "1.2.3.4" + }, + "actuator": { + "slpf": {} + }, + "args": { + "duration": 7800000000 + } + }, + "comments": [], + "assignee": null, + "type": null + } + ], + "name": "countermeasure--7d2bb069-b3ff", + "description": "Temporarily block the concerned system", + "comments": [], + "assignee": null, + "type": "openc2", + "external_ref": null, + "alert_uuid": "80ee2ccc-11e3-4416" + } + ], + "similarity_strategy": null +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_cases.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_cases.json new file mode 100644 index 000000000000..9fcfd0287e4e --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_cases.json @@ -0,0 +1,27 @@ +{ + "items": [ + { + "uuid": "05f229e7-0196-45a3", + "short_id": "CAs3AT1XeGCp", + "created_at": "2022-12-15T10:08:21.434114+00:00", + "created_by": "2514dc77-47aa-42f4", + "created_by_type": "user", + "updated_at": "2023-12-18T14:55:33.061335+00:00", + "updated_by": "2514dc77-47aa-42f4", + "updated_by_type": "user", + "title": "Test Add events", + "description": "Test Add events", + "priority": "low", + "status": "opened", + "status_uuid": "6adc2d64-87ee-4394", + "community_uuid": "52bd045f-4199-4361", + "subscribers": [], + "tags": [], + "number_of_comments": 0, + "first_seen_at": "2022-06-17T04:30:24.976000Z", + "last_seen_at": "2023-12-18T13:56:08Z", + "manual": true + } + ], + "total": 1 +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_comments.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_comments.json new file mode 100644 index 000000000000..77bf6b120e8a --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_comments.json @@ -0,0 +1,32 @@ +{ + "items": [ + { + "uuid": "40528f74-2523-428f", + "content": "Alert has been closed automatically because it is older than 2 weeks.", + "author": "apikey:f93a35e0-b9aa-4c95", + "date": 1686237010, + "created_by": "f93a35e0-b9aa-4c95", + "created_by_type": "apikey", + "unseen": false + }, + { + "uuid": "29a36b54-8ad1-4211", + "content": "This alert is always on ongoing status", + "author": "user:7114c307-d86c-4c55", + "date": 1714653288, + "created_by": "7114c307-d86c-4c55", + "created_by_type": "user", + "unseen": false + }, + { + "uuid": "0fad9131-7596-45be", + "content": "Alert is currently ongoing and will be analyzed by our team of security analysts. Update to come.", + "author": "Sekoia's security analysts", + "date": 1712073666, + "created_by": "f93a35e0-b9aa-4c95", + "created_by_type": "apikey", + "unseen": false + } + ], + "total": 3 +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_workflow.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_workflow.json new file mode 100644 index 000000000000..9a58f85bcfbd --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alert_workflow.json @@ -0,0 +1,24 @@ +{ + "actions": [ + { + "id": "937bdabf-6a08-434b", + "name": "Acknowledge", + "description": "Acknowledge the alert" + }, + { + "id": "c39a0a95-aa2c-4d0d", + "name": "Validate", + "description": "Validate the alert" + }, + { + "id": "ade85d7b-7507-4026", + "name": "Reject", + "description": "Reject the alert" + }, + { + "id": "1390be4e-ced8-4dd6", + "name": "Close", + "description": "Close the alert" + } + ] +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alerts.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alerts.json new file mode 100644 index 000000000000..86cba361a4c4 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_alerts.json @@ -0,0 +1,120 @@ +{ + "items": [ + { + "uuid": "80ee2ccc-11e3-4416", + "title": "Feed Enriched", + "created_at": 1574343159, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "updated_at": 1687958505, + "updated_by": "59899459-d385-48da", + "updated_by_type": "application", + "community_uuid": "52bd045f-4199-4361", + "short_id": "ALL1A4SKUUUU", + "entity": { + "uuid": "7f7676e7-a254-43c3", + "name": "Information Technology TEST" + }, + "urgency": { + "current_value": 20, + "value": 20, + "severity": 40, + "criticity": 0, + "display": "Moderate" + }, + "alert_type": { + "value": "brute-force", + "category": "intrusion-attempts" + }, + "status": { + "uuid": "8f206505-af6d-433e", + "name": "Acknowledged", + "description": "The alert was checked by an operator" + }, + "rule": { + "uuid": "ebcb5113-dcd1-4563", + "name": "Feed Enriched", + "description": "description test", + "severity": 40, + "type": null, + "pattern": "[ipv4-addr:value = '1.2.3.4']" + }, + "detection_type": null, + "source": "1.2.3.4", + "target": null, + "similar": 11, + "details": "details test", + "ttps": [], + "adversaries": [], + "stix": {}, + "kill_chain_short_id": "KCXKNfnJuuuu", + "number_of_total_comments": 1, + "first_seen_at": "2019-11-21T13:32:39.839600Z", + "last_seen_at": null, + "assets": [], + "time_to_detect": null, + "time_to_acknowledge": 113615345, + "time_to_respond": null, + "time_to_resolve": 111893849 + }, + { + "uuid": "07fe3fc0-ddb7-44f3", + "title": "Unauthorized IP access", + "created_at": 1574343161, + "created_by": "59899459-d385-48da", + "created_by_type": "application", + "updated_at": 1687958712, + "updated_by": "59899459-d385-48da", + "updated_by_type": "application", + "community_uuid": "52bd045f-4199-4361", + "short_id": "ALN1JwGVLxxx", + "entity": { + "uuid": "7f7676e7-a254-43c3", + "name": "Information Technology TEST" + }, + "urgency": { + "current_value": 35, + "value": 35, + "severity": 0, + "criticity": 70, + "display": "Moderate" + }, + "alert_type": { + "value": "unauthorised-information-access", + "category": "information-content-security" + }, + "status": { + "uuid": "8f206505-af6d-433e", + "name": "Acknowledged", + "description": "The alert was checked by an operator" + }, + "rule": { + "uuid": "0c5f57f6-d063-4352", + "name": "Unauthorized IP access", + "description": "Unauthorized network access from one lan to an other one", + "severity": 0, + "type": null, + "pattern": "[network-traffic:src_ref.value NOT IN ('1.2.3.4','5.6.7.8') AND network-traffic:dst_ref.value IN ('7.3.4.4') AND network-traffic:dst_port=22]" + }, + "detection_type": null, + "source": "1.2.3.4", + "target": "DMZ-01 (7.7.7.7)", + "similar": 2, + "details": "Unauthorized network access from one lan to an other one", + "ttps": [], + "adversaries": [], + "stix": {}, + "kill_chain_short_id": null, + "number_of_total_comments": 1, + "first_seen_at": "2019-11-21T13:32:41.902000Z", + "last_seen_at": null, + "assets": [ + "c50cc586-f3d9-4198" + ], + "time_to_detect": null, + "time_to_acknowledge": 113615550, + "time_to_respond": null, + "time_to_resolve": 111893860 + } + ] +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_asset.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_asset.json new file mode 100644 index 000000000000..c3edbfd14ccb --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_asset.json @@ -0,0 +1,39 @@ +{ + "uuid": "015ea33b-a7a2-4e34", + "name": "cortex_asset_test", + "category": { + "uuid": "1c646cb3-54c3-44cb", + "name": "technical" + }, + "description": null, + "criticity": { + "value": 10, + "display": "low" + }, + "asset_type": { + "uuid": "65f8ebba-e400-4ef7", + "name": "computer" + }, + "community_uuid": "52bd045f-4199-4361", + "owners": [], + "keys": [], + "attributes": [ + { + "uuid": "50b7d40c-c052-4b66", + "name": "test_attr", + "value": "0" + }, + { + "uuid": "52bfc48e-567c-45b9", + "name": "test_attr1", + "value": "1" + }, + { + "uuid": "2237d15e-f9d4-463d", + "name": "test_attr2", + "value": "2" + } + ], + "created_at": "2024-04-17T15:29:49.464479Z", + "updated_at": null +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_assets.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_assets.json new file mode 100644 index 000000000000..198ff6f73639 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_assets.json @@ -0,0 +1,88 @@ +{ + "items": [ + { + "uuid": "015ea33b-a7a2-4e34", + "name": "cortex_asset_test", + "category": { + "uuid": "1c646cb3-54c3-44cb", + "name": "technical" + }, + "description": null, + "criticity": { + "value": 10, + "display": "low" + }, + "asset_type": { + "uuid": "65f8ebba-e400-4ef7", + "name": "computer" + }, + "community_uuid": "52bd045f-4199-4361", + "owners": [], + "created_at": "2024-04-17T15:29:49.464479Z", + "updated_at": null + }, + { + "uuid": "3deb62b1-aeee-4f08", + "name": "ydi test", + "category": { + "uuid": "1c646cb3-54c3-44cb", + "name": "technical" + }, + "description": "ydi test fortisoar", + "criticity": { + "value": 28, + "display": "low" + }, + "asset_type": { + "uuid": "65f8ebba-e400-4ef7", + "name": "computer" + }, + "community_uuid": "52bd045f-4199-4361", + "owners": [], + "created_at": "2022-12-01T14:35:37.482496Z", + "updated_at": null + }, + { + "uuid": "dc14148b-8476-4b48", + "name": "cortex debug", + "category": { + "uuid": "87da56fc-1e88-467a", + "name": "people" + }, + "description": "cortex debug", + "criticity": { + "value": 90, + "display": "high" + }, + "asset_type": { + "uuid": "e47dcc10-7c1d-4922", + "name": "person" + }, + "community_uuid": "52bd045f-4199-4361", + "owners": [], + "created_at": "2022-04-06T07:40:45.908084Z", + "updated_at": "2022-04-06T07:41:07.477336Z" + }, + { + "uuid": "54d7afbc-f3e5-42df", + "name": "ADMIN", + "category": { + "uuid": "87da56fc-1e88-467a", + "name": "people" + }, + "description": "Test People Assets", + "criticity": { + "value": 90, + "display": "high" + }, + "asset_type": { + "uuid": "e47dcc10-7c1d-4922", + "name": "person" + }, + "community_uuid": "52bd045f-4199-4361", + "owners": [], + "created_at": "2022-04-06T07:02:59.038731Z", + "updated_at": null + } + ] +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_killchain.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_killchain.json new file mode 100644 index 000000000000..7e43a7b038c0 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_killchain.json @@ -0,0 +1,8 @@ +{ + "order_id": 1, + "uuid": "73708d4f-419f-44aa", + "short_id": "KCXKNfnJupq5", + "name": "Reconnaissance", + "description": "Intruder selects target, researches it, and attempts to identify vulnerabilities in the target network.", + "stix_name": "reconnaissance" +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_killchain_mirroring.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_killchain_mirroring.json new file mode 100644 index 000000000000..fee8d4f44415 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_killchain_mirroring.json @@ -0,0 +1,8 @@ +{ + "order_id": 1, + "uuid": "73708d4f-419f-44aa", + "short_id": "KCXKNfnJuUUU", + "name": "Reconnaissance", + "description": "Intruder selects target, researches it, and attempts to identify vulnerabilities in the target network.", + "stix_name": "reconnaissance" +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_user.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_user.json new file mode 100644 index 000000000000..c82c183f00ae --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_get_user.json @@ -0,0 +1,22 @@ +{ + "uuid": "7114c307-d86c-4c55", + "firstname": "Joe", + "lastname": "done", + "company_name": "sekoia.io", + "email": "joe.done@test.io", + "picture_mode": "initials", + "created_at": "2023-05-15 15:42:16.266135", + "updated_at": "2024-04-18 09:04:46.748669", + "invitation_v2": null, + "mfa_enabled": true, + "last_activity": "2024-05-02T12:32:27.196065+00:00", + "auth_provider": "local", + "communities": [ + { + "uuid": "52bd045f-4199-4361", + "name": "Sandbox", + "avatar_uuid": "d03d90b1-39f6-4da5", + "disabled": false + } + ] +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_list_assets.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_list_assets.json new file mode 100644 index 000000000000..ae3f98cf5746 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_list_assets.json @@ -0,0 +1,47 @@ +{ + "items": [ + { + "uuid": "015ea33b-a7a2-4e34", + "name": "cortex_asset_test", + "category": { + "uuid": "1c646cb3-54c3-44cb", + "name": "technical" + }, + "description": null, + "criticity": { + "value": 10, + "display": "low" + }, + "asset_type": { + "uuid": "65f8ebba-e400-4ef7", + "name": "computer" + }, + "community_uuid": "52bd045f-4199-4361", + "owners": [], + "created_at": "2024-04-17T15:29:49.464479Z", + "updated_at": null + }, + { + "uuid": "3deb62b1-aeee-4f08", + "name": "ydi test", + "category": { + "uuid": "1c646cb3-54c3-44cb", + "name": "technical" + }, + "description": "ydi test cortex", + "criticity": { + "value": 28, + "display": "low" + }, + "asset_type": { + "uuid": "65f8ebba-e400-4ef7", + "name": "computer" + }, + "community_uuid": "52bd045f-4199-4361", + "owners": [], + "created_at": "2022-12-01T14:35:37.482496Z", + "updated_at": null + } + ], + "total": 2 +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_alert_comment.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_alert_comment.json new file mode 100644 index 000000000000..619cde5bf12a --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_alert_comment.json @@ -0,0 +1,9 @@ +{ + "uuid": "00a22dd5-b54d-4eb7", + "content": "This alert is always on ongoing status", + "author": "Joe", + "date": 1714655024, + "created_by": "f870d496-a37b-4aec", + "created_by_type": "apikey", + "unseen": false +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_asset_attr.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_asset_attr.json new file mode 100644 index 000000000000..592a3753a385 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_asset_attr.json @@ -0,0 +1,5 @@ +{ + "uuid": "eac84783-d8d3-4344", + "name": "attr_test_4", + "value": "value4" +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_asset_key.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_asset_key.json new file mode 100644 index 000000000000..6401b71a3175 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_post_asset_key.json @@ -0,0 +1,5 @@ +{ + "uuid": "8007222c-f135-4f5f", + "name": "host", + "value": "computer1" +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_query_events.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_query_events.json new file mode 100644 index 000000000000..d14948346921 --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_query_events.json @@ -0,0 +1,28 @@ +{ + "uuid": "df904d2e-2c57-488f", + "status": 0, + "total": 0, + "term": "sekoiaio.intake.uuid:834a2d7f-3623-4b26", + "term_lang": "es-query-string", + "filters": [], + "created_by": "f870d496-a37b-4aec", + "created_by_type": "apikey", + "created_at": "2024-04-30T13:50:04.876962Z", + "started_at": null, + "canceled_by": null, + "canceled_by_type": null, + "canceled_at": null, + "ended_at": null, + "earliest_time": "2024-04-25T10:00:23", + "latest_time": "2024-04-25T15:00:23", + "results_ttl": 1800, + "expiration_date": null, + "expired": false, + "view_uuid": null, + "community_uuids": [ + "52bd045f-4199-4361" + ], + "only_eternal": false, + "max_last_events": null, + "date_field": null +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_query_events_status.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_query_events_status.json new file mode 100644 index 000000000000..ad3ebde3eb4c --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_query_events_status.json @@ -0,0 +1,28 @@ +{ + "uuid": "df904d2e-2c57-488f", + "status": 2, + "total": 203912, + "term": "sekoiaio.intake.uuid:834a2d7f-3623", + "term_lang": "es-query-string", + "filters": [], + "created_by": "f870d496-a37b-4aec", + "created_by_type": "apikey", + "created_at": "2024-04-30T13:56:32.338174Z", + "started_at": "2024-04-30T13:56:32.409996Z", + "canceled_by": null, + "canceled_by_type": null, + "canceled_at": null, + "ended_at": "2024-04-30T13:56:33.802894Z", + "earliest_time": "2024-04-25T10:00:23", + "latest_time": "2024-04-25T15:00:23", + "results_ttl": 1800, + "expiration_date": "2024-04-30T14:26:33.838485Z", + "expired": true, + "view_uuid": null, + "community_uuids": [ + "52bd045f-4199-4361" + ], + "only_eternal": false, + "max_last_events": null, + "date_field": null +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_retrieve_events.json b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_retrieve_events.json new file mode 100644 index 000000000000..1afffda7852a --- /dev/null +++ b/Packs/SekoiaXDR/Integrations/SekoiaXDR/test_data/SekoiaXDR_retrieve_events.json @@ -0,0 +1,124 @@ +{ + "items": [ + { + "__event_id": "ZXZlbnRzLTUyYmQwNDVmLTQxOTktNDM2MS04MjY3LWNkZWJmYzc4NDM5Mi0", + "timestamp": "2024-04-25T14:11:10.652Z", + "agent.id": "6a779e00ed1642ab91a9afcb20b4b4de371a62d28", + "agent.version": "v1.5.0+909fc425bc21b", + "process.args": "C:\\Windows\\system32\\SekoiaTest.exe", + "process.parent.args": "C:\\Windows\\system32\\SekoiaTest.exe", + "process.parent.name": "SekoiaTest.exe", + "process.parent.pid": 1002, + "process.parent.command_line": "C:\\Windows\\system32\\SekoiaTest.exe", + "process.parent.executable": "C:\\Windows\\System32\\SekoiaTest.exe", + "process.name": "processNameTest.exe", + "process.pid": 623, + "process.command_line": "\"C:\\Windows\\system32\\processNameTest.exe\" -ServerName:testserver", + "process.executable": "C:\\Windows\\system32\\processNameTest.exe", + "message": "{}", + "related.hosts": "laptop-test", + "related.ip": "1.2.3.4", + "related.user": "joe.done", + "sekoiaio.any_tag": "rfc5555, rfc1111", + "sekoiaio.process.parent_guid": "52bff9b3-fa38-4724", + "sekoiaio.process.guid": "dd924315-2807-45de", + "sekoiaio.assets.host.hostname.uuid": [ + "85dbcf0f-cc30-421e" + ], + "sekoiaio.assets.host.ip.uuid": [ + "85dbcf0f-cc30-421e" + ], + "sekoiaio.assets.host.name.uuid": [ + "85dbcf0f-cc30-421e" + ], + "sekoiaio.assets.user.name.uuid": [ + "9d99b786-6eaf-46d7" + ], + "sekoiaio.any_asset.uuid": [ + [ + "85dbcf0f-cc30-421e" + ], + [ + "9d99b786-6eaf-46d7" + ] + ], + "sekoiaio.any_asset.criticality_value": [ + [ + 0 + ], + [ + 0 + ] + ], + "sekoiaio.any_asset.name": [ + [ + "laptop-test" + ], + [ + "joe.done" + ] + ], + "sekoiaio.intake.parsing_status": "success", + "sekoiaio.intake.dialect": "sekoia.io endpoint agent", + "sekoiaio.intake.name": "Sekoia Agent ARY", + "sekoiaio.intake.dialect_uuid": "250e4095-fa08-4101", + "sekoiaio.intake.uuid": "834a2d7f-3623-4b26", + "sekoiaio.intake.key": "WJ4KkMbT8wkiFVkWpv", + "sekoiaio.entity.name": "Sekoia Agent ARY", + "sekoiaio.entity.id": "1001", + "sekoiaio.entity.uuid": "7f7676e7-a254-43c3", + "sekoiaio.tags.related.ip": [ + "rfc5735", + "rfc1918" + ], + "sekoiaio.tags.host.ip": [ + "rfc5735", + "rfc1918" + ], + "sekoiaio.customer.community_name": "Sandbox", + "sekoiaio.customer.community_uuid": "52bd045f-4199-4361", + "sekoiaio.customer.id": "Sandbox", + "host.hostname": "laptop-test", + "host.os.type": "windows", + "host.ip": "1.2.3.4", + "host.name": "laptop-test", + "action.name": "process-created", + "action.id": 1, + "action.properties.ExitStatus": "259", + "action.properties.ProviderGuid": "{3D6FA8D0-FE05-11D0}", + "action.properties.Keywords": "0x0", + "action.properties.ImageFileName": "SekoiaTest.exe", + "action.properties.PackageFullName": "", + "action.properties.SourceName": "Kernel-Process", + "action.properties.Severity": "LOG_ALWAYS", + "action.properties.UniqueProcessKey": "0xFFFFB3811111111", + "action.properties.Flags": "0", + "action.properties.ApplicationId": "", + "action.properties.SessionId": "2", + "action.properties.DirectoryTableBase": "0x933E111", + "action.outcome": "success", + "event.code": "1", + "event.dialect": "sekoia.io endpoint agent", + "event.provider": "SEKOIA-IO", + "event.created": "2024-04-25T14:11:28.073386+00:00", + "event.action": "process-created", + "event.id": "0b83c211-6e79-4a28", + "event.dialect_uuid": "250e4095-fa08-4101", + "event.type": "creation", + "event.category": "process", + "event.outcome": "success", + "user.domain": "DomainTEST", + "user.name": "joe.done", + "entity.name": "IT test", + "entity.id": "1000", + "entity.uuid": "7f7676e7-a254-43c3", + "customer.intake_key": "WJ4KkMbT8wkiFVk", + "customer.community_name": "Sandbox", + "customer.intake_uuid": "834a2d7f-3623-4b26", + "customer.community_uuid": "52bd045f-4199-4361", + "customer.id": "Sandbox", + "customer.intake_name": "Sekoia Agent ARY" + } + ], + "total": 1 +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/Layouts/layoutscontainer-Sekoia_XDR_Layout.json b/Packs/SekoiaXDR/Layouts/layoutscontainer-Sekoia_XDR_Layout.json new file mode 100644 index 000000000000..2771f660ab27 --- /dev/null +++ b/Packs/SekoiaXDR/Layouts/layoutscontainer-Sekoia_XDR_Layout.json @@ -0,0 +1,1650 @@ +{ + "close": { + "sections": [ + { + "description": "", + "fields": [ + { + "fieldId": "incident_sekoiaxdralertreject", + "isVisible": true + } + ], + "isVisible": true, + "name": "Basic Information", + "query": null, + "queryType": "", + "readOnly": false, + "type": "" + } + ] + }, + "detailsV2": { + "tabs": [ + { + "id": "summary", + "name": "Legacy Summary", + "type": "summary" + }, + { + "id": "caseinfoid", + "name": "Incident Info", + "sections": [ + { + "displayType": "ROW", + "h": 2, + "i": "caseinfoid-field-changed-caseinfoid-hmim4odmnc-caseinfoid-fce71720-98b0-11e9-97d7-ed26ef9e46c8", + "isVisible": true, + "items": [ + { + "endCol": 2, + "fieldId": "alertid", + "height": 22, + "id": "b23cf510-a62a-11ed-85fd-253a4b8fc4fa", + "index": 0, + "sectionItemType": "field", + "startCol": 0 + }, + { + "endCol": 2, + "fieldId": "severity", + "height": 22, + "id": "incident-severity-field", + "index": 2, + "sectionItemType": "field", + "startCol": 0 + }, + { + "endCol": 2, + "fieldId": "owner", + "height": 22, + "id": "incident-owner-field", + "index": 3, + "sectionItemType": "field", + "startCol": 0 + }, + { + "dropEffect": "move", + "endCol": 2, + "fieldId": "alertcategory", + "height": 22, + "id": "2a4e39e0-a669-11ed-9ed8-a3cadf5e5136", + "index": 4, + "listId": "caseinfoid-fce71720-98b0-11e9-97d7-ed26ef9e46c8", + "sectionItemType": "field", + "startCol": 0 + }, + { + "dropEffect": "move", + "endCol": 2, + "fieldId": "alerttypeid", + "height": 22, + "id": "1cb738e0-a669-11ed-9ed8-a3cadf5e5136", + "index": 5, + "listId": "caseinfoid-fce71720-98b0-11e9-97d7-ed26ef9e46c8", + "sectionItemType": "field", + "startCol": 0 + }, + { + "dropEffect": "move", + "endCol": 2, + "fieldId": "type", + "height": 22, + "id": "incident-type-field", + "index": 6, + "listId": "caseinfoid-fce71720-98b0-11e9-97d7-ed26ef9e46c8", + "sectionItemType": "field", + "startCol": 0 + }, + { + "endCol": 2, + "fieldId": "sourcebrand", + "height": 22, + "id": "incident-sourceBrand-field", + "index": 7, + "sectionItemType": "field", + "startCol": 0 + }, + { + "endCol": 2, + "fieldId": "sourceinstance", + "height": 22, + "id": "incident-sourceInstance-field", + "index": 8, + "sectionItemType": "field", + "startCol": 0 + }, + { + "endCol": 2, + "fieldId": "roles", + "height": 22, + "id": "647c0670-a0c3-11ed-a83a-21e09acc789a", + "index": 9, + "sectionItemType": "field", + "startCol": 0 + }, + { + "endCol": 2, + "fieldId": "xsoarreadonlyroles", + "height": 22, + "id": "660a95b0-a0c3-11ed-a83a-21e09acc789a", + "index": 10, + "sectionItemType": "field", + "startCol": 0 + }, + { + "endCol": 2, + "fieldId": "playbookid", + "height": 22, + "id": "incident-playbookId-field", + "index": 11, + "sectionItemType": "field", + "startCol": 0 + } + ], + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Case Details", + "static": false, + "w": 1, + "x": 0, + "y": 0 + }, + { + "h": 2, + "i": "caseinfoid-field-changed-caseinfoid-hmim4odmnc-caseinfoid-61263cc0-98b1-11e9-97d7-ed26ef9e46c8", + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Notes", + "static": false, + "type": "notes", + "w": 1, + "x": 2, + "y": 0 + }, + { + "displayType": "ROW", + "h": 2, + "i": "caseinfoid-field-changed-caseinfoid-hmim4odmnc-caseinfoid-6aabad20-98b1-11e9-97d7-ed26ef9e46c8", + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Work Plan", + "static": false, + "type": "workplan", + "w": 1, + "x": 1, + "y": 0 + }, + { + "displayType": "ROW", + "h": 2, + "i": "caseinfoid-field-changed-caseinfoid-hmim4odmnc-caseinfoid-770ec200-98b1-11e9-97d7-ed26ef9e46c8", + "isVisible": true, + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Linked Incidents", + "static": false, + "type": "linkedIncidents", + "w": 1, + "x": 1, + "y": 6 + }, + { + "displayType": "ROW", + "h": 2, + "i": "caseinfoid-field-changed-caseinfoid-hmim4odmnc-caseinfoid-842632c0-98b1-11e9-97d7-ed26ef9e46c8", + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Child Incidents", + "static": false, + "type": "childInv", + "w": 2, + "x": 0, + "y": 8 + }, + { + "displayType": "ROW", + "h": 2, + "i": "caseinfoid-field-changed-caseinfoid-hmim4odmnc-caseinfoid-4a31afa0-98ba-11e9-a519-93a53c759fe0", + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Evidence", + "static": false, + "type": "evidence", + "w": 1, + "x": 2, + "y": 6 + }, + { + "displayType": "ROW", + "h": 2, + "hideName": false, + "i": "caseinfoid-field-changed-caseinfoid-hmim4odmnc-caseinfoid-7717e580-9bed-11e9-9a3f-8b4b2158e260", + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Team Members", + "static": false, + "type": "team", + "w": 1, + "x": 2, + "y": 8 + }, + { + "columns": [ + { + "displayed": true, + "isDefault": true, + "key": "indicator_type", + "width": 120 + }, + { + "displayed": true, + "isDefault": true, + "key": "value", + "width": 300 + }, + { + "displayed": true, + "isDefault": true, + "key": "score", + "width": 120 + }, + { + "displayed": true, + "isDefault": true, + "key": "firstSeen", + "width": 275 + }, + { + "displayed": true, + "isDefault": true, + "key": "lastSeen", + "width": 275 + }, + { + "displayed": true, + "isDefault": true, + "key": "timestamp", + "width": 190 + }, + { + "displayed": true, + "isDefault": true, + "key": "relatedIncCount", + "width": 150 + }, + { + "displayed": true, + "isDefault": true, + "key": "sourceBrands", + "width": 175 + }, + { + "displayed": true, + "isDefault": true, + "key": "sourceInstances", + "width": 175 + }, + { + "displayed": true, + "isDefault": true, + "key": "expirationStatus", + "width": 175 + }, + { + "displayed": true, + "isDefault": true, + "key": "expiration", + "width": 190 + } + ], + "displayType": "ROW", + "h": 2, + "i": "caseinfoid-field-changed-caseinfoid-hmim4odmnc-caseinfoid-7ce69dd0-a07f-11e9-936c-5395a1acf11e", + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Indicators", + "query": "", + "queryType": "input", + "static": false, + "type": "indicators", + "w": 3, + "x": 0, + "y": 4 + }, + { + "displayType": "CARD", + "h": 2, + "i": "caseinfoid-field-changed-caseinfoid-hmim4odmnc-caseinfoid-ac32f620-a0b0-11e9-b27f-13ae1773d289", + "items": [ + { + "endCol": 1, + "fieldId": "occurred", + "height": 53, + "id": "incident-occurred-field", + "index": 0, + "sectionItemType": "field", + "startCol": 0 + }, + { + "endCol": 1, + "fieldId": "dbotmodified", + "height": 53, + "id": "incident-modified-field", + "index": 1, + "sectionItemType": "field", + "startCol": 0 + }, + { + "endCol": 1, + "fieldId": "dbotduedate", + "height": 53, + "id": "incident-dueDate-field", + "index": 2, + "sectionItemType": "field", + "startCol": 0 + }, + { + "endCol": 2, + "fieldId": "dbotcreated", + "height": 53, + "id": "incident-created-field", + "index": 0, + "sectionItemType": "field", + "startCol": 1 + }, + { + "endCol": 2, + "fieldId": "dbotclosed", + "height": 53, + "id": "incident-closed-field", + "index": 1, + "sectionItemType": "field", + "startCol": 1 + }, + { + "dropEffect": "move", + "endCol": 2, + "fieldId": "sourcecreatetime", + "height": 53, + "id": "dbea2c00-a668-11ed-9ed8-a3cadf5e5136", + "index": 4, + "listId": "caseinfoid-ac32f620-a0b0-11e9-b27f-13ae1773d289", + "sectionItemType": "field", + "startCol": 1 + } + ], + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Timeline Information", + "static": false, + "w": 1, + "x": 0, + "y": 2 + }, + { + "displayType": "CARD", + "h": 2, + "i": "caseinfoid-field-changed-caseinfoid-hmim4odmnc-caseinfoid-88e6bf70-a0b1-11e9-b27f-13ae1773d289", + "isVisible": true, + "items": [ + { + "endCol": 2, + "fieldId": "dbotclosed", + "height": 22, + "id": "incident-dbotClosed-field", + "index": 0, + "sectionItemType": "field", + "startCol": 0 + }, + { + "endCol": 2, + "fieldId": "closereason", + "height": 22, + "id": "incident-closeReason-field", + "index": 1, + "sectionItemType": "field", + "startCol": 0 + }, + { + "endCol": 2, + "fieldId": "closenotes", + "height": 44, + "id": "incident-closeNotes-field", + "index": 2, + "sectionItemType": "field", + "startCol": 0 + } + ], + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Closing Information", + "static": false, + "w": 1, + "x": 0, + "y": 6 + }, + { + "displayType": "CARD", + "h": 2, + "i": "caseinfoid-field-changed-caseinfoid-hmim4odmnc-caseinfoid-e54b1770-a0b1-11e9-b27f-13ae1773d289", + "isVisible": true, + "items": [ + { + "endCol": 2, + "fieldId": "details", + "height": 106, + "id": "incident-details-field", + "index": 0, + "sectionItemType": "field", + "startCol": 0 + } + ], + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Investigation Data", + "static": false, + "w": 1, + "x": 1, + "y": 2 + }, + { + "displayType": "ROW", + "h": 2, + "hideName": false, + "i": "caseinfoid-field-changed-caseinfoid-hmim4odmnc-caseinfoid-79249190-a669-11ed-9ed8-a3cadf5e5136", + "items": [ + { + "endCol": 2, + "fieldId": "alertsource", + "height": 22, + "id": "a7d27d40-a669-11ed-9ed8-a3cadf5e5136", + "index": 0, + "sectionItemType": "field", + "startCol": 0 + }, + { + "endCol": 2, + "fieldId": "target", + "height": 22, + "id": "b24ad920-a669-11ed-9ed8-a3cadf5e5136", + "index": 1, + "sectionItemType": "field", + "startCol": 0 + }, + { + "endCol": 2, + "fieldId": "description", + "height": 22, + "id": "ad2d7dd0-a669-11ed-9ed8-a3cadf5e5136", + "index": 2, + "sectionItemType": "field", + "startCol": 0 + } + ], + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Details", + "static": false, + "w": 1, + "x": 2, + "y": 2 + } + ], + "type": "custom" + }, + { + "hidden": false, + "id": "xwqxiqdriy", + "name": "Sekoia Alert", + "sections": [ + { + "h": 3, + "hideName": false, + "i": "xwqxiqdriy-field-changed-xwqxiqdriy-caseinfoid-xwqxiqdriy-field-changed-xwqxiqdriy-caseinfoid-xwqxiqdriy-caseinfoid-7bde8760-a95c-11ed-9145-25ddf42500b6", + "items": [], + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Comments", + "query": "SekoiaXDRPrintComments", + "queryType": "script", + "static": false, + "type": "dynamic", + "w": 3, + "x": 0, + "y": 4 + }, + { + "displayType": "ROW", + "h": 2, + "hideName": false, + "i": "xwqxiqdriy-field-changed-xwqxiqdriy-caseinfoid-xwqxiqdriy-field-changed-xwqxiqdriy-caseinfoid-xwqxiqdriy-caseinfoid-7ece0630-a95c-11ed-9145-25ddf42500b6", + "items": [ + { + "endCol": 2, + "fieldId": "alertid", + "height": 22, + "id": "907fe6a0-a95c-11ed-9145-25ddf42500b6", + "index": 0, + "sectionItemType": "field", + "startCol": 0 + }, + { + "endCol": 2, + "fieldId": "alertcategory", + "height": 22, + "id": "a884bc30-a95c-11ed-9145-25ddf42500b6", + "index": 1, + "sectionItemType": "field", + "startCol": 0 + }, + { + "endCol": 2, + "fieldId": "alerttypeid", + "height": 22, + "id": "ab392dd0-a95c-11ed-9145-25ddf42500b6", + "index": 2, + "sectionItemType": "field", + "startCol": 0 + }, + { + "endCol": 2, + "fieldId": "sourcecreatetime", + "height": 22, + "id": "bb027820-a95c-11ed-9145-25ddf42500b6", + "index": 3, + "sectionItemType": "field", + "startCol": 0 + }, + { + "dropEffect": "move", + "endCol": 2, + "fieldId": "sekoiaxdralertstatus", + "height": 22, + "id": "a3e43c80-d3a2-11ed-a53e-9fbb99147542", + "index": 4, + "listId": "caseinfoid-7ece0630-a95c-11ed-9145-25ddf42500b6", + "sectionItemType": "field", + "startCol": 0 + }, + { + "args": { + "comment": { + "simple": "", + "userMarkedRequired": true + }, + "short_id": { + "complex": { + "accessor": "alertid", + "filters": [], + "root": "incident", + "transformers": [] + } + } + }, + "buttonClass": "primary", + "dropEffect": "move", + "endCol": 2, + "fieldId": "", + "height": 44, + "id": "58473820-dd09-11ed-8e0f-4badd587f193", + "index": 5, + "listId": "caseinfoid-xwqxiqdriy-caseinfoid-7ece0630-a95c-11ed-9145-25ddf42500b6", + "name": "UPDATE STATUS", + "scriptId": "SekoiaXDRChangeStatus", + "sectionItemType": "button", + "startCol": 0 + }, + { + "args": { + "short_id": { + "complex": { + "accessor": "alertid", + "filters": [], + "root": "incident", + "transformers": [] + } + } + }, + "buttonClass": "success", + "endCol": 2, + "fieldId": "", + "height": 44, + "id": "ef9d3e80-ce87-11ed-81c5-57f992291288", + "index": 6, + "name": "ADD COMMENT", + "scriptId": "SekoiaXDRAddComment", + "sectionItemType": "button", + "startCol": 0 + } + ], + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Alert information", + "static": false, + "w": 1, + "x": 0, + "y": 0 + }, + { + "displayType": "ROW", + "h": 4, + "hideItemTitleOnlyOne": true, + "hideName": false, + "i": "xwqxiqdriy-field-changed-xwqxiqdriy-caseinfoid-xwqxiqdriy-field-changed-xwqxiqdriy-caseinfoid-xwqxiqdriy-caseinfoid-06bcc2c0-a95d-11ed-9145-25ddf42500b6", + "items": [ + { + "endCol": 2, + "fieldId": "sekoiaxdralertdetails", + "height": 44, + "id": "45a64580-d381-11ed-a53d-9fbb99147542", + "index": 0, + "sectionItemType": "field", + "startCol": 0 + } + ], + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Details", + "static": false, + "w": 1, + "x": 2, + "y": 0 + }, + { + "h": 2, + "hideName": false, + "i": "xwqxiqdriy-field-changed-xwqxiqdriy-caseinfoid-xwqxiqdriy-field-changed-xwqxiqdriy-caseinfoid-xwqxiqdriy-caseinfoid-c0be8e90-ac48-11ed-bd2d-994e9b5e36b1", + "items": [], + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Case Information", + "query": "SekoiaXDRPrintCase", + "queryType": "script", + "static": false, + "type": "dynamic", + "w": 1, + "x": 1, + "y": 2 + }, + { + "displayType": "ROW", + "h": 2, + "hideItemTitleOnlyOne": true, + "hideName": false, + "i": "xwqxiqdriy-field-changed-xwqxiqdriy-caseinfoid-xwqxiqdriy-field-changed-xwqxiqdriy-caseinfoid-xwqxiqdriy-caseinfoid-ccc1c7d0-d848-11ed-a2c5-afbbb72993fe", + "items": [ + { + "endCol": 2, + "fieldId": "sekoiaxdrkillchain", + "height": 106, + "id": "d4996120-d848-11ed-a2c5-afbbb72993fe", + "index": 0, + "sectionItemType": "field", + "startCol": 0 + } + ], + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Kill Chain", + "static": false, + "w": 1, + "x": 0, + "y": 2 + }, + { + "h": 2, + "hideName": true, + "i": "xwqxiqdriy-field-changed-xwqxiqdriy-308b91c0-3d3c-11ef-bbb1-2b336ca0953c", + "items": [], + "maxW": 3, + "minH": 1, + "moved": false, + "name": "Impacted assets", + "query": "SekoiaXDRPrintAssets", + "queryType": "script", + "static": false, + "type": "dynamic", + "w": 1, + "x": 1, + "y": 0 + } + ], + "type": "custom" + }, + { + "id": "warRoom", + "name": "War Room", + "type": "warRoom" + }, + { + "id": "workPlan", + "name": "Work Plan", + "type": "workPlan" + }, + { + "id": "evidenceBoard", + "name": "Evidence Board", + "type": "evidenceBoard" + }, + { + "id": "relatedIncidents", + "name": "Related Incidents", + "type": "relatedIncidents" + }, + { + "id": "canvas", + "name": "Canvas", + "type": "canvas" + } + ] + }, + "edit": { + "sections": [ + { + "description": "", + "fields": [ + { + "fieldId": "incident_name", + "isVisible": true + }, + { + "fieldId": "incident_occurred", + "isVisible": true + }, + { + "fieldId": "incident_reminder", + "isVisible": true + }, + { + "fieldId": "incident_owner", + "isVisible": true + }, + { + "fieldId": "incident_roles", + "isVisible": true + }, + { + "fieldId": "incident_type", + "isVisible": true + }, + { + "fieldId": "incident_severity", + "isVisible": true + }, + { + "fieldId": "incident_playbookid", + "isVisible": true + }, + { + "fieldId": "incident_labels", + "isVisible": true + }, + { + "fieldId": "incident_phase", + "isVisible": true + }, + { + "fieldId": "incident_details", + "isVisible": true + }, + { + "fieldId": "incident_attachment", + "isVisible": true + } + ], + "isVisible": true, + "name": "Basic Information", + "query": null, + "queryType": "", + "readOnly": false, + "type": "" + }, + { + "description": "", + "fields": [ + { + "fieldId": "incident_asn", + "isVisible": true + }, + { + "fieldId": "incident_asnname", + "isVisible": true + }, + { + "fieldId": "incident_accountmemberof", + "isVisible": true + }, + { + "fieldId": "incident_accountstatus", + "isVisible": true + }, + { + "fieldId": "incident_additionaldata", + "isVisible": true + }, + { + "fieldId": "incident_additionalindicators", + "isVisible": true + }, + { + "fieldId": "incident_agentid", + "isVisible": true + }, + { + "fieldId": "incident_agentversion", + "isVisible": true + }, + { + "fieldId": "incident_agentsid", + "isVisible": true + }, + { + "fieldId": "incident_alertcategory", + "isVisible": true + }, + { + "fieldId": "incident_alertid", + "isVisible": true + }, + { + "fieldId": "incident_alertname", + "isVisible": true + }, + { + "fieldId": "incident_alertsource", + "isVisible": true + }, + { + "fieldId": "incident_alerttypeid", + "isVisible": true + }, + { + "fieldId": "incident_alerturl", + "isVisible": true + }, + { + "fieldId": "incident_app", + "isVisible": true + }, + { + "fieldId": "incident_appmessage", + "isVisible": true + }, + { + "fieldId": "incident_assigneduser", + "isVisible": true + }, + { + "fieldId": "incident_assignmentgroup", + "isVisible": true + }, + { + "fieldId": "incident_birthday", + "isVisible": true + }, + { + "fieldId": "incident_cmd", + "isVisible": true + }, + { + "fieldId": "incident_cmdline", + "isVisible": true + }, + { + "fieldId": "incident_cvelist", + "isVisible": true + }, + { + "fieldId": "incident_caller", + "isVisible": true + }, + { + "fieldId": "incident_categories", + "isVisible": true + }, + { + "fieldId": "incident_changed", + "isVisible": true + }, + { + "fieldId": "incident_childprocess", + "isVisible": true + }, + { + "fieldId": "incident_classification", + "isVisible": true + }, + { + "fieldId": "incident_cloudaccountid", + "isVisible": true + }, + { + "fieldId": "incident_cloudinstanceid", + "isVisible": true + }, + { + "fieldId": "incident_commandline", + "isVisible": true + }, + { + "fieldId": "incident_comment", + "isVisible": true + }, + { + "fieldId": "incident_country", + "isVisible": true + }, + { + "fieldId": "incident_countrycode", + "isVisible": true + }, + { + "fieldId": "incident_countrycodenumber", + "isVisible": true + }, + { + "fieldId": "incident_description", + "isVisible": true + }, + { + "fieldId": "incident_destinationhostname", + "isVisible": true + }, + { + "fieldId": "incident_destinationip", + "isVisible": true + }, + { + "fieldId": "incident_destinationnetwork", + "isVisible": true + }, + { + "fieldId": "incident_destinationnetworks", + "isVisible": true + }, + { + "fieldId": "incident_destinationport", + "isVisible": true + }, + { + "fieldId": "incident_detectedendpoints", + "isVisible": true + }, + { + "fieldId": "incident_detectedips", + "isVisible": true + }, + { + "fieldId": "incident_detecteduser", + "isVisible": true + }, + { + "fieldId": "incident_detectionurl", + "isVisible": true + }, + { + "fieldId": "incident_deviceexternalip", + "isVisible": true + }, + { + "fieldId": "incident_deviceexternalips", + "isVisible": true + }, + { + "fieldId": "incident_devicehash", + "isVisible": true + }, + { + "fieldId": "incident_deviceid", + "isVisible": true + }, + { + "fieldId": "incident_deviceinternalips", + "isVisible": true + }, + { + "fieldId": "incident_devicelocalip", + "isVisible": true + }, + { + "fieldId": "incident_devicemacaddress", + "isVisible": true + }, + { + "fieldId": "incident_devicemodel", + "isVisible": true + }, + { + "fieldId": "incident_devicename", + "isVisible": true + }, + { + "fieldId": "incident_deviceosname", + "isVisible": true + }, + { + "fieldId": "incident_deviceosversion", + "isVisible": true + }, + { + "fieldId": "incident_deviceou", + "isVisible": true + }, + { + "fieldId": "incident_deviceusername", + "isVisible": true + }, + { + "fieldId": "incident_domainname", + "isVisible": true + }, + { + "fieldId": "incident_dsts", + "isVisible": true + }, + { + "fieldId": "incident_endpoint", + "isVisible": true + }, + { + "fieldId": "incident_endpointisolationstatus", + "isVisible": true + }, + { + "fieldId": "incident_escalation", + "isVisible": true + }, + { + "fieldId": "incident_eventid", + "isVisible": true + }, + { + "fieldId": "incident_eventtype", + "isVisible": true + }, + { + "fieldId": "incident_events", + "isVisible": true + }, + { + "fieldId": "incident_externalcategoryid", + "isVisible": true + }, + { + "fieldId": "incident_externalcategoryname", + "isVisible": true + }, + { + "fieldId": "incident_externalconfidence", + "isVisible": true + }, + { + "fieldId": "incident_externalendtime", + "isVisible": true + }, + { + "fieldId": "incident_externallink", + "isVisible": true + }, + { + "fieldId": "incident_externalseverity", + "isVisible": true + }, + { + "fieldId": "incident_externalstarttime", + "isVisible": true + }, + { + "fieldId": "incident_externalstatus", + "isVisible": true + }, + { + "fieldId": "incident_externalsubcategoryid", + "isVisible": true + }, + { + "fieldId": "incident_externalsubcategoryname", + "isVisible": true + }, + { + "fieldId": "incident_externalsystemid", + "isVisible": true + }, + { + "fieldId": "incident_filehash", + "isVisible": true + }, + { + "fieldId": "incident_filemd5", + "isVisible": true + }, + { + "fieldId": "incident_filename", + "isVisible": true + }, + { + "fieldId": "incident_filenames", + "isVisible": true + }, + { + "fieldId": "incident_filepath", + "isVisible": true + }, + { + "fieldId": "incident_filepaths", + "isVisible": true + }, + { + "fieldId": "incident_filerelationships", + "isVisible": true + }, + { + "fieldId": "incident_filesha1", + "isVisible": true + }, + { + "fieldId": "incident_filesha256", + "isVisible": true + }, + { + "fieldId": "incident_filesize", + "isVisible": true + }, + { + "fieldId": "incident_fileupload", + "isVisible": true + }, + { + "fieldId": "incident_firstname", + "isVisible": true + }, + { + "fieldId": "incident_fullname", + "isVisible": true + }, + { + "fieldId": "incident_hostnames", + "isVisible": true + }, + { + "fieldId": "incident_huntresultscount", + "isVisible": true + }, + { + "fieldId": "incident_ipblockedstatus", + "isVisible": true + }, + { + "fieldId": "incident_ipreputation", + "isVisible": true + }, + { + "fieldId": "incident_incidentlink", + "isVisible": true + }, + { + "fieldId": "incident_incomingmirrorerror", + "isVisible": true + }, + { + "fieldId": "incident_investigationstage", + "isVisible": true + }, + { + "fieldId": "incident_isactive", + "isVisible": true + }, + { + "fieldId": "incident_lastname", + "isVisible": true + }, + { + "fieldId": "incident_logsource", + "isVisible": true + }, + { + "fieldId": "incident_lowlevelcategoriesevents", + "isVisible": true + }, + { + "fieldId": "incident_macaddress", + "isVisible": true + }, + { + "fieldId": "incident_md5", + "isVisible": true + }, + { + "fieldId": "incident_mitretacticid", + "isVisible": true + }, + { + "fieldId": "incident_mitretacticname", + "isVisible": true + }, + { + "fieldId": "incident_mitretechniqueid", + "isVisible": true + }, + { + "fieldId": "incident_mitretechniquename", + "isVisible": true + }, + { + "fieldId": "incident_mobiledevicemodel", + "isVisible": true + }, + { + "fieldId": "incident_numberofrelatedincidents", + "isVisible": true + }, + { + "fieldId": "incident_numberofsimilarfiles", + "isVisible": true + }, + { + "fieldId": "incident_os", + "isVisible": true + }, + { + "fieldId": "incident_ostype", + "isVisible": true + }, + { + "fieldId": "incident_osversion", + "isVisible": true + }, + { + "fieldId": "incident_objective", + "isVisible": true + }, + { + "fieldId": "incident_orglevel1", + "isVisible": true + }, + { + "fieldId": "incident_orglevel2", + "isVisible": true + }, + { + "fieldId": "incident_orglevel3", + "isVisible": true + }, + { + "fieldId": "incident_orgunit", + "isVisible": true + }, + { + "fieldId": "incident_outgoingmirrorerror", + "isVisible": true + }, + { + "fieldId": "incident_pid", + "isVisible": true + }, + { + "fieldId": "incident_parentcmdline", + "isVisible": true + }, + { + "fieldId": "incident_parentprocess", + "isVisible": true + }, + { + "fieldId": "incident_parentprocesscmd", + "isVisible": true + }, + { + "fieldId": "incident_parentprocessfilepath", + "isVisible": true + }, + { + "fieldId": "incident_parentprocessids", + "isVisible": true + }, + { + "fieldId": "incident_parentprocessmd5", + "isVisible": true + }, + { + "fieldId": "incident_parentprocessname", + "isVisible": true + }, + { + "fieldId": "incident_parentprocesspath", + "isVisible": true + }, + { + "fieldId": "incident_parentprocesssha256", + "isVisible": true + }, + { + "fieldId": "incident_passwordchangeddate", + "isVisible": true + }, + { + "fieldId": "incident_phonenumber", + "isVisible": true + }, + { + "fieldId": "incident_policyactions", + "isVisible": true + }, + { + "fieldId": "incident_processcmd", + "isVisible": true + }, + { + "fieldId": "incident_processcreationtime", + "isVisible": true + }, + { + "fieldId": "incident_processid", + "isVisible": true + }, + { + "fieldId": "incident_processmd5", + "isVisible": true + }, + { + "fieldId": "incident_processname", + "isVisible": true + }, + { + "fieldId": "incident_processnames", + "isVisible": true + }, + { + "fieldId": "incident_processpath", + "isVisible": true + }, + { + "fieldId": "incident_processpaths", + "isVisible": true + }, + { + "fieldId": "incident_processsha256", + "isVisible": true + }, + { + "fieldId": "incident_protocol", + "isVisible": true + }, + { + "fieldId": "incident_protocolnames", + "isVisible": true + }, + { + "fieldId": "incident_registryhive", + "isVisible": true + }, + { + "fieldId": "incident_registrykey", + "isVisible": true + }, + { + "fieldId": "incident_registryvalue", + "isVisible": true + }, + { + "fieldId": "incident_registryvaluetype", + "isVisible": true + }, + { + "fieldId": "incident_relatedendpoints", + "isVisible": true + }, + { + "fieldId": "incident_relatedreport", + "isVisible": true + }, + { + "fieldId": "incident_renderedhtml", + "isVisible": true + }, + { + "fieldId": "incident_rulename", + "isVisible": true + }, + { + "fieldId": "incident_sha1", + "isVisible": true + }, + { + "fieldId": "incident_sha256", + "isVisible": true + }, + { + "fieldId": "incident_sha512", + "isVisible": true + }, + { + "fieldId": "incident_ssdeep", + "isVisible": true + }, + { + "fieldId": "incident_scenario", + "isVisible": true + }, + { + "fieldId": "incident_selectedindicators", + "isVisible": true + }, + { + "fieldId": "incident_similarincidentsdbot", + "isVisible": true + }, + { + "fieldId": "incident_sourcecategory", + "isVisible": true + }, + { + "fieldId": "incident_sourcecreatetime", + "isVisible": true + }, + { + "fieldId": "incident_sourcecreatedby", + "isVisible": true + }, + { + "fieldId": "incident_sourceexternalips", + "isVisible": true + }, + { + "fieldId": "incident_sourcehostname", + "isVisible": true + }, + { + "fieldId": "incident_sourceip", + "isVisible": true + }, + { + "fieldId": "incident_sourceid", + "isVisible": true + }, + { + "fieldId": "incident_sourcenetwork", + "isVisible": true + }, + { + "fieldId": "incident_sourcenetworks", + "isVisible": true + }, + { + "fieldId": "incident_sourceport", + "isVisible": true + }, + { + "fieldId": "incident_sourcepriority", + "isVisible": true + }, + { + "fieldId": "incident_sourcestatus", + "isVisible": true + }, + { + "fieldId": "incident_sourceupdatedby", + "isVisible": true + }, + { + "fieldId": "incident_sourceusername", + "isVisible": true + }, + { + "fieldId": "incident_srcs", + "isVisible": true + }, + { + "fieldId": "incident_state", + "isVisible": true + }, + { + "fieldId": "incident_subcategory", + "isVisible": true + }, + { + "fieldId": "incident_tactic", + "isVisible": true + }, + { + "fieldId": "incident_tacticid", + "isVisible": true + }, + { + "fieldId": "incident_tags", + "isVisible": true + }, + { + "fieldId": "incident_target", + "isVisible": true + }, + { + "fieldId": "incident_teamname", + "isVisible": true + }, + { + "fieldId": "incident_technique", + "isVisible": true + }, + { + "fieldId": "incident_techniqueid", + "isVisible": true + }, + { + "fieldId": "incident_tenantname", + "isVisible": true + }, + { + "fieldId": "incident_threatfamilyname", + "isVisible": true + }, + { + "fieldId": "incident_threathuntingdetectedhostnames", + "isVisible": true + }, + { + "fieldId": "incident_threathuntingdetectedip", + "isVisible": true + }, + { + "fieldId": "incident_threatname", + "isVisible": true + }, + { + "fieldId": "incident_ticketacknowledgeddate", + "isVisible": true + }, + { + "fieldId": "incident_ticketcloseddate", + "isVisible": true + }, + { + "fieldId": "incident_ticketnumber", + "isVisible": true + }, + { + "fieldId": "incident_ticketopeneddate", + "isVisible": true + }, + { + "fieldId": "incident_urlsslverification", + "isVisible": true + }, + { + "fieldId": "incident_urls", + "isVisible": true + }, + { + "fieldId": "incident_usecasedescription", + "isVisible": true + }, + { + "fieldId": "incident_usercreationtime", + "isVisible": true + }, + { + "fieldId": "incident_userengagementresponse", + "isVisible": true + }, + { + "fieldId": "incident_usersid", + "isVisible": true + }, + { + "fieldId": "incident_users", + "isVisible": true + }, + { + "fieldId": "incident_verdict", + "isVisible": true + }, + { + "fieldId": "incident_appchannelname", + "isVisible": true + }, + { + "fieldId": "incident_similarincidents", + "isVisible": true + }, + { + "fieldId": "incident_useraccountcontrol", + "isVisible": true + } + ], + "isVisible": true, + "name": "Custom Fields", + "query": null, + "queryType": "", + "readOnly": false, + "type": "" + } + ] + }, + "group": "incident", + "id": "Sekoia XDR Layout", + "name": "Sekoia XDR Layout", + "system": false, + "version": -1, + "fromVersion": "6.10.0", + "marketplaces": [ + "xsoar" + ], + "description": "" +} \ No newline at end of file diff --git a/Packs/SekoiaXDR/README.md b/Packs/SekoiaXDR/README.md new file mode 100644 index 000000000000..4f4a43201a4a --- /dev/null +++ b/Packs/SekoiaXDR/README.md @@ -0,0 +1,13 @@ +# Sekoia Defend (XDR) + +## What does this pack do? + +Sekoia Defend (XDR) pack is a comprehensive solution designed to enhance your cybersecurity operations. It offers several key functionalities to streamline and fortify your security infrastructure: + +- **Retrieve Assets and Perform Actions**: This pack enables you to fetch detailed information about various assets within your network. You can also execute some actions on these assets. + +- **Collect Alerts and Respond Accordingly**: The pack is equipped to gather security alerts from different sources. Once alerts are collected, it can trigger predefined actions to mitigate potential threats, ensuring swift and effective incident response. + +- **Query and Analyze Events**: The pack allows you to query security events in real time. This feature is crucial for analyzing the context and impact of security incidents, helping you understand and respond to them more accurately and promptly. + +By integrating these features, Sekoia Defend (XDR) pack helps you maintain a robust and proactive security posture, effectively protecting your organization's digital assets against evolving threats. \ No newline at end of file diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRAddComment/README.md b/Packs/SekoiaXDR/Scripts/SekoiaXDRAddComment/README.md new file mode 100644 index 000000000000..32b9c13fe54b --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRAddComment/README.md @@ -0,0 +1,25 @@ +Script to add a comment to an alert in Sekoia, including the name of the person who made the comment. + +## Script Data + +--- + +| **Name** | **Description** | +| --- | --- | +| Script Type | python3 | +| Tags | incident-action-button | +| Cortex XSOAR Version | 6.10.0 | + +## Inputs + +--- + +| **Argument Name** | **Description** | +| --- | --- | +| short_id | The short ID of the alert. | +| comment | The comment you want to send to an alert. | + +## Outputs + +--- +There are no outputs for this script. diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRAddComment/SekoiaXDRAddComment.py b/Packs/SekoiaXDR/Scripts/SekoiaXDRAddComment/SekoiaXDRAddComment.py new file mode 100644 index 000000000000..db43bb5c73c4 --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRAddComment/SekoiaXDRAddComment.py @@ -0,0 +1,36 @@ +import demistomock as demisto # noqa: F401 +from CommonServerPython import * # noqa: F401 + + +def get_username(): + get_users = execute_command("getUsers", {"current": "true"}) + username = get_users[0]["name"] # type: ignore + return username + + +def post_comment(alert_short_id: str, comment: Optional[str], author: str): + try: + execute_command( + "sekoia-xdr-post-comment-alert", + {"id": alert_short_id, "comment": comment, "author": author}, + ) + except Exception as e: + return_error( + f"Failed to post comment for alert with id {alert_short_id} : {str(e)}" + ) + + +def main(): + alert_short_id = demisto.args()["short_id"] + comment = demisto.args().get("comment") + + user = get_username() + post_comment(alert_short_id, comment, user) + readable_output = f"### Comment added by {user}:\n {comment}" + + command_results = CommandResults(readable_output=readable_output) + return_results(command_results) + + +if __name__ in ["__main__", "builtin", "builtins"]: + main() diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRAddComment/SekoiaXDRAddComment.yml b/Packs/SekoiaXDR/Scripts/SekoiaXDRAddComment/SekoiaXDRAddComment.yml new file mode 100644 index 000000000000..991183848695 --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRAddComment/SekoiaXDRAddComment.yml @@ -0,0 +1,26 @@ +commonfields: + id: SekoiaXDRAddComment + version: -1 +name: SekoiaXDRAddComment +script: '' +type: python +tags: +- incident-action-button +comment: Script to add a comment to an alert in Sekoia, including the name of the person who made the comment. +enabled: true +args: +- name: short_id + required: true + description: The short ID of the alert. +- name: comment + required: true + description: The comment you want to send to an alert. +scripttarget: 0 +subtype: python3 +runonce: false +dockerimage: demisto/python3:3.11.10.111039 +runas: DBotWeakRole +engineinfo: {} +fromversion: 6.10.0 +tests: +- No tests (auto formatted) diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRAddComment/SekoiaXDRAddComment_test.py b/Packs/SekoiaXDR/Scripts/SekoiaXDRAddComment/SekoiaXDRAddComment_test.py new file mode 100644 index 000000000000..e10ab893ef76 --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRAddComment/SekoiaXDRAddComment_test.py @@ -0,0 +1,33 @@ +import demistomock as demisto +from SekoiaXDRAddComment import get_username, post_comment, main # type: ignore + + +def test_get_username(mocker): + output_data = [ + {"Type": 3, "Contents": [{"name": "admin", "PrettyRoles": "Administrator"}]} + ] + mocker.patch.object(demisto, "executeCommand", return_value=output_data) + assert get_username() == "admin" + + +def test_post_comment(mocker): + output_data = [ + {"Type": 3, "Contents": [{"id": "1", "comment": "test", "author": "admin"}]} + ] + mocker.patch.object(demisto, "executeCommand", return_value=output_data) + assert not post_comment("1", "test", "admin") + + +def test_main(mocker): + mocker.patch.object( + demisto, "args", return_value={"short_id": "1", "comment": "test"} + ) + mocker.patch("SekoiaXDRAddComment.get_username", return_value="admin") + mocker.patch("SekoiaXDRAddComment.post_comment", return_value=None) + mocker.patch.object(demisto, "results") + + main() + assert ( + demisto.results.call_args[0][0]["HumanReadable"] + == "### Comment added by admin:\n test" + ) diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRChangeStatus/README.md b/Packs/SekoiaXDR/Scripts/SekoiaXDRChangeStatus/README.md new file mode 100644 index 000000000000..a3b21a8e931c --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRChangeStatus/README.md @@ -0,0 +1,25 @@ +This script changes the status of the Sekoia alert in XSOAR. + +## Script Data + +--- + +| **Name** | **Description** | +| --- | --- | +| Script Type | python3 | +| Tags | incident-action-button | +| Cortex XSOAR Version | 6.10.0 | + +## Inputs + +--- + +| **Argument Name** | **Description** | +| --- | --- | +| short_id | The short ID of the alert. | +| status | Status to change on the Sekoia alert. | + +## Outputs + +--- +There are no outputs for this script. diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRChangeStatus/SekoiaXDRChangeStatus.py b/Packs/SekoiaXDR/Scripts/SekoiaXDRChangeStatus/SekoiaXDRChangeStatus.py new file mode 100644 index 000000000000..e1662e6e6a15 --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRChangeStatus/SekoiaXDRChangeStatus.py @@ -0,0 +1,31 @@ +import demistomock as demisto # noqa: F401 +from CommonServerPython import * # noqa: F401 + + +def update_status(new_status: str): + execute_command("setIncident", {"sekoiaxdralertstatus": new_status}) + + +def main(): + alert_short_id = demisto.args()["short_id"] + new_status = demisto.args()["status"] + + if new_status in ["Ongoing", "Acknowledged"]: + update_status(new_status) + readable_output = f"### Status of the alert changed to:\n {new_status}" + return_results( + { + "ContentsFormat": formats["markdown"], + "Type": entryTypes["note"], + "Contents": readable_output, + } + ) + else: + raise Exception( + f"Alert {alert_short_id} could not be changed to that status. \ + Please reject or close the Sekoia Alert by closing the XSOAR incident using the XSOAR close incident button." + ) + + +if __name__ in ["__main__", "builtin", "builtins"]: + main() diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRChangeStatus/SekoiaXDRChangeStatus.yml b/Packs/SekoiaXDR/Scripts/SekoiaXDRChangeStatus/SekoiaXDRChangeStatus.yml new file mode 100644 index 000000000000..6bfdf887e400 --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRChangeStatus/SekoiaXDRChangeStatus.yml @@ -0,0 +1,30 @@ +commonfields: + id: SekoiaXDRChangeStatus + version: -1 +name: SekoiaXDRChangeStatus +script: '' +type: python +tags: +- incident-action-button +comment: This script changes the status of the Sekoia alert in XSOAR. +enabled: true +args: +- name: short_id + required: true + description: The short ID of the alert. +- name: status + required: true + auto: PREDEFINED + predefined: + - Ongoing + - Acknowledged + description: Status to change on the Sekoia alert. +scripttarget: 0 +subtype: python3 +runonce: false +dockerimage: demisto/python3:3.11.10.111039 +runas: DBotWeakRole +engineinfo: {} +fromversion: 6.10.0 +tests: +- No tests (auto formatted) diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRChangeStatus/SekoiaXDRChangeStatus_test.py b/Packs/SekoiaXDR/Scripts/SekoiaXDRChangeStatus/SekoiaXDRChangeStatus_test.py new file mode 100644 index 000000000000..e794965a0586 --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRChangeStatus/SekoiaXDRChangeStatus_test.py @@ -0,0 +1,16 @@ +import demistomock as demisto +from SekoiaXDRChangeStatus import main # type: ignore + + +def test_main(mocker): + mocker.patch.object( + demisto, + "args", + return_value={"short_id": "1", "status": "Ongoing"}, + ) + mocker.patch.object(demisto, "results") + main() + assert ( + demisto.results.call_args[0][0]["Contents"] + == "### Status of the alert changed to:\n Ongoing" + ) diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRCloseAlert/README.md b/Packs/SekoiaXDR/Scripts/SekoiaXDRCloseAlert/README.md new file mode 100644 index 000000000000..0fee2c26fcf6 --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRCloseAlert/README.md @@ -0,0 +1,21 @@ +Post-processing script to close XSOAR incident. + +## Script Data + +--- + +| **Name** | **Description** | +| --- | --- | +| Script Type | python3 | +| Tags | post-processing | +| Cortex XSOAR Version | 6.10.0 | + +## Inputs + +--- +There are no inputs for this script. + +## Outputs + +--- +There are no outputs for this script. diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRCloseAlert/SekoiaXDRCloseAlert.py b/Packs/SekoiaXDR/Scripts/SekoiaXDRCloseAlert/SekoiaXDRCloseAlert.py new file mode 100644 index 000000000000..a7902d842583 --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRCloseAlert/SekoiaXDRCloseAlert.py @@ -0,0 +1,50 @@ +import demistomock as demisto # noqa: F401 +from CommonServerPython import * # noqa: F401 + + +def get_status_name(alert_id: str): + get_alert = execute_command("sekoia-xdr-get-alert", {"id": alert_id}) + return get_alert["status"]["name"] # type: ignore + + +def close_alert( + alert_id: str, + reject: str, + close_reason: Optional[str], + close_notes: Optional[str], + username: str, +): + readable_output = "" + alert_status = get_status_name(alert_id) + if alert_status not in ["Closed", "Rejected"]: + if reject == "false": + execute_command("setIncident", {"sekoiaxdralertstatus": "Closed"}) + readable_output = f"**** The alert {alert_id} has been closed. ****" + if reject == "true": + execute_command("setIncident", {"sekoiaxdralertstatus": "Rejected"}) + readable_output = f"**** The alert {alert_id} has been rejected. ****" + + return_results( + { + "ContentsFormat": formats["markdown"], + "Type": entryTypes["note"], + "Contents": readable_output, + } + ) + + +def main(): + incident = demisto.incidents()[0] # type: ignore + alert_short_id = incident.get("CustomFields", {}).get("alertid") + reject = demisto.getArg("sekoiaxdralertreject") # type: ignore + close_reason = demisto.getArg("closeReason") + close_notes = demisto.getArg("closeNotes") + username = demisto.getArg("closingUserId") # type: ignore + + close_alert( + alert_short_id, reject, close_reason, close_notes, username # type: ignore + ) + + +if __name__ in ("__main__", "__builtin__", "builtins"): + main() diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRCloseAlert/SekoiaXDRCloseAlert.yml b/Packs/SekoiaXDR/Scripts/SekoiaXDRCloseAlert/SekoiaXDRCloseAlert.yml new file mode 100644 index 000000000000..d6d1baf8270f --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRCloseAlert/SekoiaXDRCloseAlert.yml @@ -0,0 +1,19 @@ +commonfields: + id: CloseSekoiaAlert + version: -1 +name: CloseSekoiaAlert +script: '' +type: python +tags: +- post-processing +comment: Post-processing script to close XSOAR incident. +enabled: true +scripttarget: 0 +subtype: python3 +runonce: false +dockerimage: demisto/python3:3.11.10.111039 +runas: DBotWeakRole +engineinfo: {} +fromversion: 6.10.0 +tests: +- No tests (auto formatted) diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRCloseAlert/SekoiaXDRCloseAlert_test.py b/Packs/SekoiaXDR/Scripts/SekoiaXDRCloseAlert/SekoiaXDRCloseAlert_test.py new file mode 100644 index 000000000000..80510ed38b26 --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRCloseAlert/SekoiaXDRCloseAlert_test.py @@ -0,0 +1,51 @@ +import demistomock as demisto +import SekoiaXDRCloseAlert # type: ignore +from SekoiaXDRCloseAlert import get_status_name, close_alert, main # type: ignore + + +def test_get_status_name(mocker): + output_data = [{"Type": 3, "Contents": {"status": {"name": "Ongoing"}}}] + mocker.patch.object(demisto, "executeCommand", return_value=output_data) + assert get_status_name("1") == "Ongoing" + + +def test_close_alert(mocker): + mocker.patch.object(SekoiaXDRCloseAlert, "get_status_name", return_value="Ongoing") + output_data = [{"Type": 3, "Contents": {}}] + mocker.patch.object(demisto, "executeCommand", return_value=output_data) + mocker.patch.object(demisto, "results") + close_alert("1", "false", "reason", "notes", "admin") + assert ( + demisto.results.call_args[0][0]["Contents"] + == "**** The alert 1 has been closed. ****" + ) + + close_alert("1", "true", "reason", "notes", "admin") + assert ( + demisto.results.call_args[0][0]["Contents"] + == "**** The alert 1 has been rejected. ****" + ) + + mocker.patch.object(SekoiaXDRCloseAlert, "get_status_name", return_value="Closed") + try: + close_alert("1", "false", "reason", "notes", "admin") + except Exception as e: + assert str(e) == "**** The alert is already closed or rejected. ****" + + +def test_main(mocker): + mocker.patch.object( + demisto, + "incidents", + return_value=[ + { + "dbotMirrorDirection": "Out", + "CustomFields": {"alertid": "1"}, + "owner": "admin", + } + ], + ) + mocker.patch.object(demisto, "getArg", return_value="admin") + mocker.patch.object(SekoiaXDRCloseAlert, "close_alert", return_value=None) + + assert main() is None diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintAssets/README.md b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintAssets/README.md new file mode 100644 index 000000000000..29bb4d9acaa2 --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintAssets/README.md @@ -0,0 +1,21 @@ +Print all assets by incident. + +## Script Data + +--- + +| **Name** | **Description** | +| --- | --- | +| Script Type | python3 | +| Tags | dynamic-section | +| Cortex XSOAR Version | 6.10.0 | + +## Inputs + +--- +There are no inputs for this script. + +## Outputs + +--- +There are no outputs for this script. diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintAssets/SekoiaXDRPrintAssets.py b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintAssets/SekoiaXDRPrintAssets.py new file mode 100644 index 000000000000..fbedcf2520ea --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintAssets/SekoiaXDRPrintAssets.py @@ -0,0 +1,50 @@ +import demistomock as demisto # noqa: F401 +from CommonServerPython import * # noqa: F401 + + +def get_assets_info(assets_ids: list): + assets_infos = [] + for asset in assets_ids: + asset_infos = execute_command("sekoia-xdr-get-asset", {"asset_uuid": asset}) + asset_dict = { + "name": asset_infos["name"], # type: ignore + "description": asset_infos["description"], # type: ignore + } + assets_infos.append(asset_dict) + return assets_infos + + +def get_assets_ids(alert_uuid: str): + try: + alert_infos = execute_command("sekoia-xdr-get-alert", {"id": alert_uuid}) + except Exception as e: + return_error(f"Failed to get alert information: {str(e)}") + + assets_ids = alert_infos.get("assets") # type: ignore + if assets_ids: + assets_infos = get_assets_info(assets_ids) + headers = ["name", "description"] + readable_output = tableToMarkdown( + "Impacted assets:", assets_infos, headers=headers + ) + else: + readable_output = ( + "### {{color:green}}(There is no case information related to this alert.)" + ) + + return readable_output + + +def main(): + incident = demisto.incident() + alert_uuid = incident.get("CustomFields", {}).get("alertid") + + readable_output = get_assets_ids(alert_uuid) + command_results = CommandResults(readable_output=readable_output) + return_results(command_results) + + +""" ENTRY POINT """ + +if __name__ in ("__main__", "__builtin__", "builtins"): + main() diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintAssets/SekoiaXDRPrintAssets.yml b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintAssets/SekoiaXDRPrintAssets.yml new file mode 100644 index 000000000000..1338f523a55a --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintAssets/SekoiaXDRPrintAssets.yml @@ -0,0 +1,19 @@ +commonfields: + id: SekoiaXDRPrintAssets + version: -1 +name: SekoiaXDRPrintAssets +script: '' +type: python +tags: +- dynamic-section +comment: Print all assets by incident. +enabled: true +scripttarget: 0 +subtype: python3 +runonce: false +dockerimage: demisto/python3:3.11.10.111039 +runas: DBotWeakRole +engineinfo: {} +fromversion: 6.10.0 +tests: +- No tests (auto formatted) diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintAssets/SekoiaXDRPrintAssets_test.py b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintAssets/SekoiaXDRPrintAssets_test.py new file mode 100644 index 000000000000..f8ddd8203ac1 --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintAssets/SekoiaXDRPrintAssets_test.py @@ -0,0 +1,30 @@ +import demistomock as demisto +import SekoiaXDRPrintAssets + + +def test_assets_info(mocker): + assets_ids = ["1", "2"] + asset = { + "name": "asset", + "description": "description", + } + mocker.patch.object( + demisto, "executeCommand", return_value=[{"Type": 3, "Contents": asset}] + ) + assert len(SekoiaXDRPrintAssets.get_assets_info(assets_ids)) == 2 + + +def test_assets_ids(mocker): + alert_infos = {"assets": ["1", "2"]} + assets_infos = [ + {"description": "alVEdEMFNEMcBTNodDPL", "name": "name1"}, + {"description": "alVEdEMFNEazedadazedL", "name": "name2"}, + ] + mocker.patch.object( + demisto, "executeCommand", return_value=[{"Type": 3, "Contents": alert_infos}] + ) + mocker.patch.object( + SekoiaXDRPrintAssets, "get_assets_info", return_value=assets_infos + ) + assert "name1" in SekoiaXDRPrintAssets.get_assets_ids("1234") + assert "name2" in SekoiaXDRPrintAssets.get_assets_ids("1234") diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintCase/README.md b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintCase/README.md new file mode 100644 index 000000000000..2287313742eb --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintCase/README.md @@ -0,0 +1,21 @@ +Prints case details from the Sekoia alert. + +## Script Data + +--- + +| **Name** | **Description** | +| --- | --- | +| Script Type | python3 | +| Tags | dynamic-section | +| Cortex XSOAR Version | 6.10.0 | + +## Inputs + +--- +There are no inputs for this script. + +## Outputs + +--- +There are no outputs for this script. diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintCase/SekoiaXDRPrintCase.py b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintCase/SekoiaXDRPrintCase.py new file mode 100644 index 000000000000..bccf4a7e1d97 --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintCase/SekoiaXDRPrintCase.py @@ -0,0 +1,54 @@ +import demistomock as demisto # noqa: F401 +from CommonServerPython import * # noqa: F401 + + +def create_case_object(cases): + return [ + { + "title": case_item["title"], + "description": case_item["description"], + "status": case_item["status"].capitalize(), + "priority": case_item["priority"].capitalize(), + "related alerts": ", ".join( + [alert["short_id"] for alert in case_item["alerts"]] + ), + } + for case_item in cases + ] + + +def get_case_info(alert_uuid: str): + readable_output = "" + try: + cases = execute_command("sekoia-xdr-get-cases-alert", {"alert_id": alert_uuid}) + except Exception as e: + return_error(f"Failed to get case information: {str(e)}") + + if cases: + readable_cases = create_case_object(cases) + headers = ["title", "description", "status", "priority", "related alerts"] + readable_output = tableToMarkdown( + "Cases information:", readable_cases, headers=headers + ) + else: + readable_output = ( + "### {{color:green}}(There is no case information related to this alert.)" + ) + + return readable_output + + +def main(): + incident = demisto.incident() + alert_uuid = incident.get("CustomFields", {}).get("alertid") + + readable_output = get_case_info(alert_uuid) + + command_results = CommandResults(readable_output=readable_output) + return_results(command_results) + + +""" ENTRY POINT """ + +if __name__ in ("__main__", "__builtin__", "builtins"): + main() diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintCase/SekoiaXDRPrintCase.yml b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintCase/SekoiaXDRPrintCase.yml new file mode 100644 index 000000000000..1e0fc1f1b918 --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintCase/SekoiaXDRPrintCase.yml @@ -0,0 +1,19 @@ +commonfields: + id: SekoiaXDRPrintCase + version: -1 +name: SekoiaXDRPrintCase +script: '' +type: python +tags: +- dynamic-section +comment: Prints case details from the Sekoia alert. +enabled: true +scripttarget: 0 +subtype: python3 +runonce: false +dockerimage: demisto/python3:3.11.10.111039 +runas: DBotWeakRole +engineinfo: {} +fromversion: 6.10.0 +tests: +- No tests (auto formatted) diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintCase/SekoiaXDRPrintCase_test.py b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintCase/SekoiaXDRPrintCase_test.py new file mode 100644 index 000000000000..1661488608ce --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintCase/SekoiaXDRPrintCase_test.py @@ -0,0 +1,90 @@ +import demistomock as demisto +from SekoiaXDRPrintCase import get_case_info, create_case_object, main # type: ignore + + +def test_create_case_object(): + cases = [ + { + "title": "title1", + "description": "description1", + "short_id": "11", + "status": "status1", + "priority": "priority1", + "alerts": [{"short_id": "1"}, {"short_id": "2"}, {"short_id": "3"}], + }, + { + "title": "title2", + "description": "description2", + "short_id": "22", + "status": "status2", + "priority": "priority2", + "alerts": [{"short_id": "4"}, {"short_id": "5"}, {"short_id": "6"}], + }, + ] + expected = [ + { + "title": "title1", + "description": "description1", + "status": "Status1", + "priority": "Priority1", + "related alerts": "1, 2, 3", + }, + { + "title": "title2", + "description": "description2", + "status": "Status2", + "priority": "Priority2", + "related alerts": "4, 5, 6", + }, + ] + assert create_case_object(cases) == expected + + +def test_get_case_info(mocker): + cases_output = [ + { + "title": "title1", + "description": "description1", + "short_id": "11", + "status": "status1", + "priority": "priority1", + "alerts": [{"short_id": "1"}, {"short_id": "2"}, {"short_id": "3"}], + }, + { + "title": "title2", + "description": "description2", + "short_id": "22", + "status": "status2", + "priority": "priority2", + "alerts": [{"short_id": "4"}, {"short_id": "5"}, {"short_id": "6"}], + }, + ] + mocker.patch.object( + demisto, "executeCommand", return_value=[{"Type": 3, "Contents": cases_output}] + ) + assert "title1" in get_case_info("1") + assert "title2" in get_case_info("1") + assert "1, 2, 3" in get_case_info("1") + + +def test_main(mocker): + mocker.patch.object( + demisto, "incident", return_value={"CustomFields": {"caseid": "1"}} + ) + mocker.patch( + "SekoiaXDRPrintCase.get_case_info", + return_value="### Case Info:\n\ + |title|description|status|priority|related alerts|\n\ + |---|---|---|---|---|\n\ + | title1 | description1 | Status1 | Priority1 | 1, 2, 3 |\n", + ) + mocker.patch.object(demisto, "results") + + main() + assert ( + demisto.results.call_args[0][0]["HumanReadable"] + == "### Case Info:\n\ + |title|description|status|priority|related alerts|\n\ + |---|---|---|---|---|\n\ + | title1 | description1 | Status1 | Priority1 | 1, 2, 3 |\n" + ) diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintComments/README.md b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintComments/README.md new file mode 100644 index 000000000000..f2ebbec7a2b4 --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintComments/README.md @@ -0,0 +1,21 @@ +Prints the comments fetched from the Sekoia alert in a table format. + +## Script Data + +--- + +| **Name** | **Description** | +| --- | --- | +| Script Type | python3 | +| Tags | dynamic-section | +| Cortex XSOAR Version | 6.10.0 | + +## Inputs + +--- +There are no inputs for this script. + +## Outputs + +--- +There are no outputs for this script. diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintComments/SekoiaXDRPrintComments.py b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintComments/SekoiaXDRPrintComments.py new file mode 100644 index 000000000000..f0e79138750e --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintComments/SekoiaXDRPrintComments.py @@ -0,0 +1,50 @@ +import demistomock as demisto # noqa: F401 +from CommonServerPython import * # noqa: F401 + + +def create_comment_object(comments): + return [ + { + "date": comment_item["date"], + "comment": comment_item["content"], + "user": comment_item["user"], + } + for comment_item in comments + ] + + +def get_comments(alert_id: str): + readable_output = "" + try: + comments = execute_command("sekoia-xdr-get-comments", {"id": alert_id}) + except Exception as e: + return_error(f"Failed to get comments: {str(e)}") + + if len(comments) > 0: # type: ignore + readable_comments = create_comment_object(comments) + headers = ["date", "comment", "user"] + readable_output = tableToMarkdown( + "Comments:", readable_comments, headers=headers + ) + else: + readable_output = ( + "### Comments:\n ### {{color:green}}(There is no comments in this alert.)" + ) + + return readable_output + + +def main(): + incident = demisto.incident() + alert_short_id = incident.get("CustomFields", {}).get("alertid") + + readable_output = get_comments(alert_short_id) + + command_results = CommandResults(readable_output=readable_output) + return_results(command_results) + + +""" ENTRY POINT """ + +if __name__ in ("__main__", "__builtin__", "builtins"): + main() diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintComments/SekoiaXDRPrintComments.yml b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintComments/SekoiaXDRPrintComments.yml new file mode 100644 index 000000000000..3ca571803028 --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintComments/SekoiaXDRPrintComments.yml @@ -0,0 +1,19 @@ +commonfields: + id: SekoiaXDRPrintComments + version: -1 +name: SekoiaXDRPrintComments +script: '' +type: python +tags: +- dynamic-section +comment: Prints the comments fetched from the Sekoia alert in a table format. +enabled: true +scripttarget: 0 +subtype: python3 +runonce: false +dockerimage: demisto/python3:3.11.10.111039 +runas: DBotWeakRole +engineinfo: {} +fromversion: 6.10.0 +tests: +- No tests (auto formatted) diff --git a/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintComments/SekoiaXDRPrintComments_test.py b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintComments/SekoiaXDRPrintComments_test.py new file mode 100644 index 000000000000..16da1cf8e7bf --- /dev/null +++ b/Packs/SekoiaXDR/Scripts/SekoiaXDRPrintComments/SekoiaXDRPrintComments_test.py @@ -0,0 +1,93 @@ +import demistomock as demisto +from SekoiaXDRPrintComments import create_comment_object, get_comments, main # type: ignore + + +def test_create_comment_object(mocker): + comments = [ + { + "date": "2021-07-27T15:00:00Z", + "content": "comment", + "user": "user", + "field_1": "value_1", + "field_2": "value_2", + "field_3": "value_3", + "field_4": "value_4", + }, + { + "date": "2021-07-27T15:00:00Z", + "content": "comment1", + "user": "user1", + "field_1": "value_1", + "field_2": "value_2", + "field_3": "value_3", + "field_4": "value_4", + }, + ] + expected = [ + { + "date": "2021-07-27T15:00:00Z", + "comment": "comment", + "user": "user", + }, + { + "date": "2021-07-27T15:00:00Z", + "comment": "comment1", + "user": "user1", + }, + ] + assert create_comment_object(comments) == expected + + +def test_get_comments(mocker): + comments_output = [ + { + "date": "2021-07-27T15:00:00Z", + "content": "comment", + "user": "user", + "field_1": "value_1", + "field_2": "value_2", + "field_3": "value_3", + "field_4": "value_4", + }, + { + "date": "2021-07-27T15:00:00Z", + "content": "comment1", + "user": "user1", + "field_1": "value_1", + "field_2": "value_2", + "field_3": "value_3", + "field_4": "value_4", + }, + ] + mocker.patch.object( + demisto, + "executeCommand", + return_value=[{"Type": 3, "Contents": comments_output}], + ) + assert "user" in get_comments("alert_id") + assert "user1" in get_comments("alert_id") + assert "comment" in get_comments("alert_id") + assert "comment1" in get_comments("alert_id") + + +def test_get_comments_no_comments(mocker): + comments_output = [] + mocker.patch.object( + demisto, + "executeCommand", + return_value=[{"Type": 3, "Contents": comments_output}], + ) + assert "There is no comments in this alert" in get_comments("alert_id") + + +def test_main(mocker): + mocker.patch.object( + demisto, "incident", return_value={"CustomFields": {"alertid": "alert_id"}} + ) + mocker.patch( + "SekoiaXDRPrintComments.get_comments", return_value="Comments: testcomment" + ) + mocker.patch.object(demisto, "results") + + main() + assert demisto.results.call_args[0][0]["HumanReadable"] == "Comments: testcomment" diff --git a/Packs/SekoiaXDR/pack_metadata.json b/Packs/SekoiaXDR/pack_metadata.json new file mode 100644 index 000000000000..b7a7ffe1d1c7 --- /dev/null +++ b/Packs/SekoiaXDR/pack_metadata.json @@ -0,0 +1,23 @@ +{ + "name": "SekoiaXDR", + "description": "Request Sekoia Defend (XDR) from Cortex XSOAR", + "support": "partner", + "currentVersion": "1.0.0", + "author": "SEKOIA.IO", + "url": "https://www.sekoia.io/en/contact/", + "email": "contact@sekoia.io", + "categories": [ + "Data Enrichment & Threat Intelligence" + ], + "tags": [], + "useCases": [], + "keywords": [], + "marketplaces": [ + "xsoar", + "marketplacev2" + ], + "devEmail": [ + "team-integration@sekoia.io" + ], + "githubUser": [] +} \ No newline at end of file