NetskopeAPIv1
Get alerts and events, manage quarantine files as well as URL and hash lists using Netskope API v1.
Network Security · Netskope
Details
| ID | NetskopeAPIv1 |
|---|---|
| Provider | Netskope |
| Category | Network Security |
| From Version | 6.2.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
Netskope (API v1)
Get alerts and events, manage quarantine files as well as URL and hash lists using Netskope API v1.
This integration was integrated and tested with version 93.0.7.625 of Netskope.
Configure Netskope in Cortex
| Parameter | Description | Required |
|---|---|---|
| Server URL | True | |
| API token | True | |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False | |
| Fetch incidents | False | |
| Maximum incidents per fetch | False | |
| First fetch timestamp (<number> <time unit>, like 12 hours, 7 days) | False | |
| Fetch Events | Fetch events as incidents, in addition to the alerts. | False |
| Event types to fetch | False | |
| Maximum events as incidents per fetch | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
netskope-event-list
Get events extracted from SaaS traffic and or logs.
Base Command
netskope-event-list
Input
| Argument Name | Description | Required |
|---|---|---|
| query | Free query to filter the events. For example, “app eq Dropbox”. For more information, please visit Netskope documentation: https://docs.netskope.com/en/get-events-data.html’ | Optional |
| event_type | Select events by their type. Possible values are: page, application, audit, infrastructure, network. | Required |
| timeperiod | Get all events from a certain time period. Possible values are: Last 60 mins, Last 24 Hrs, Last 7 Days, Last 30 Days. | Optional |
| start_time | Restrict events to those that have timestamps greater than the provided timestamp. | Optional |
| end_time | Restrict events to those that have timestamps less than or equal to the provided timestamp. | Optional |
| insertion_start_time | Restrict events to those that were inserted to the system after the provided timestamp. | Optional |
| insertion_end_time | Restrict events to those that were inserted to the system before the provided timestamp. | Optional |
| limit | The maximum amount of events to retrieve. Default is 50. | Optional |
| page | The page number of the events to retrieve (minimum is 1). Default is 1. | Optional |
| unsorted | If true, the returned data will not be sorted (useful for improved performance). Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Netskope.Event.event_id | String | The unique identifier of the event. |
| Netskope.Event.timestamp | Number | Unix epoch timestamp when the event happened in. |
| Netskope.Event.type | String | Shows if it is an application event or a connection event. |
| Netskope.Event.access_method | String | Cloud app traffic can be steered to the Netskope cloud using different deployment methods such as Client (Netskope Client), Secure Forwarder etc. |
| Netskope.Event.traffic_type | String | Type of the traffic: CloudApp or Web. |
| Netskope.Event.count | Number | Number of raw log lines/events sessionized or suppressed during the suppressed interval. |
| Netskope.Event.app | String | Specific cloud application used by the user (e.g. app = Dropbox). |
| Netskope.Event.appcategory | String | Application Category as designated by Netskope. |
| Netskope.Event.url | String | URL of the application that the user visited as provided by the log or data plane traffic. |
| Netskope.Event.page | String | The URL of the originating page. |
| Netskope.Event.domain | String | Domain value. |
| Netskope.Event.object | String | Name of the object which is being acted on. |
| Netskope.Event.object_id | String | Unique ID associated with an object. |
| Netskope.Event.activity | String | Description of the user performed activity. |
| Netskope.Event.device | String | Device type from where the user accessed the cloud app. |
| Netskope.Event.category | String | The event category. |
Command example
!netskope-event-list event_type=application limit=1 start_time=2021-03-21T18:48:02.358736 end_time=2022-03-21T18:48:02.358736
Context Example
{
"Netskope": {
"Event": {
"_insertion_epoch_timestamp": 1647890592,
"access_method": "API Connector",
"activity": "Create",
"alert": "no",
"app": "Google Workspace",
"appcategory": "Application Suite",
"audit_category": null,
"audit_type": "authorize",
"browser": "unknown",
"category": "Application Suite",
"cci": 91,
"ccl": "excellent",
"count": 1,
"device": "Other",
"event_id": "a3f6cb3f22c4431defbf371b",
"from_user": "test@goxsoar.com",
"from_user_category": "Internal",
"instance_id": "goxsoar.com",
"netskope_activity": "False",
"object": "BetterCloud",
"object_id": "800521135851.apps.googleusercontent.com",
"object_type": "Token",
"organization_unit": "",
"os": "unknown",
"other_categories": [],
"scopes": [
"https://apps-apis.google.com/a/feeds/calendar/resource/",
"https://apps-apis.google.com/a/feeds/compliance/audit/",
"https://apps-apis.google.com/a/feeds/domain/",
"https://apps-apis.google.com/a/feeds/emailsettings/2.0/",
"https://docs.google.com/feeds/",
"https://sites.google.com/feeds/",
"https://spreadsheets.google.com/feeds/",
"https://www.google.com/m8/feeds/",
"https://www.googleapis.com/auth/contacts",
"https://www.googleapis.com/auth/activity",
"https://www.googleapis.com/auth/admin.datatransfer",
"https://www.googleapis.com/auth/admin.directory.group",
"https://www.googleapis.com/auth/admin.directory.group.member",
"https://www.googleapis.com/auth/admin.directory.orgunit",
"https://www.googleapis.com/auth/admin.directory.user",
"https://www.googleapis.com/auth/admin.directory.user.alias",
"https://www.googleapis.com/auth/admin.directory.user.security",
"https://www.googleapis.com/auth/admin.directory.userschema",
"https://www.googleapis.com/auth/admin.reports.audit.readonly",
"https://www.googleapis.com/auth/admin.reports.usage.readonly",
"https://www.googleapis.com/auth/apps.groups.settings",
"https://www.googleapis.com/auth/apps.licensing",
"https://www.googleapis.com/auth/calendar",
"https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/gmail.settings.basic",
"https://www.googleapis.com/auth/gmail.settings.sharing"
],
"site": "Google App Suite",
"srcip": "fda3:e722:ac3:10:15:8d06:a37:f8d0",
"timestamp": 1647888482,
"traffic_type": "CloudApp",
"type": "nspolicy",
"ur_normalized": "test@goxsoar.com",
"user": "test@goxsoar.com",
"user_category": "Internal",
"userip": "fda3:e722:ac3:10:15:8d06:a37:f8d0",
"userkey": "test@goxsoar.com"
}
}
}
Human Readable Output
Events List
Current page size: 1
Showing page 1 out of others that may exist.
Event Id Timestamp Type Access Method App Traffic Type a3f6cb3f22c4431defbf371b 1647888482 nspolicy API Connector Google Workspace CloudApp
netskope-alert-list
Get alerts generated by Netskope, including policy, DLP, and watch list alerts.
Base Command
netskope-alert-list
Input
| Argument Name | Description | Required |
|---|---|---|
| query | Free query to filter the alerts. For example, “alert_name like ‘test’”. For more information, please visit Netskope documentation: https://docs.netskope.com/en/get-alerts-data.html’ | Optional |
| alert_type | Select alerts by their type. Possible values are: anomaly, Compromised Credential, policy, Legal Hold, malsite, Malware, DLP, Security Assessment, watchlist, quarantine, Remediation, uba. | Optional |
| acked | Whether to retrieve acknowledged alerts or not. Possible values are: true, false. | Optional |
| timeperiod | Get alerts from certain time period. Possible values are: Last 60 mins, Last 24 Hrs, Last 7 Days, Last 30 days, Last 60 days, Last 90 days. | Optional |
| start_time | Restrict alerts to those that have timestamps greater than the provided timestamp. | Optional |
| end_time | Restrict alerts to those that have timestamps less than or equal to the provided timestamp. | Optional |
| insertion_start_time | Restrict alerts which have been inserted into the system after the provided timestamp. | Optional |
| insertion_end_time | Restrict alerts which have been inserted into the system before the provided timestamp. | Optional |
| limit | The maximum number of alerts to return. Default is 50. | Optional |
| page | The page number of the alerts to retrieve (minimum is 1). Default is 1. | Optional |
| unsorted | If true, the returned data will not be sorted (useful for improved performance). Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Netskope.Alert.alert_id | String | The unique identifier of the alert. |
| Netskope.Alert.timestamp | Number | Timestamp when the event/alert happened. |
| Netskope.Alert.type | String | Shows if it is an application event or a connection event. |
| Netskope.Alert.access_method | String | Cloud app traffic can be steered to the Netskope cloud using different deployment methods such as Client (Netskope Client), Secure Forwarder etc. |
| Netskope.Alert.traffic_type | String | Type of the traffic: CloudApp or Web. |
| Netskope.Alert.action | String | Action taken on the event for the policy. |
| Netskope.Alert.count | Number | Number of raw log lines/events sessionized or suppressed during the suppressed interval. |
| Netskope.Alert.alert_name | String | Name of the alert. |
| Netskope.Alert.alert_type | String | Type of the alert. |
| Netskope.Alert.acked | Boolean | Whether user acknowledged the alert or not. |
| Netskope.Alert.policy | String | Name of the policy configured by an admin. |
| Netskope.Alert.app | String | Specific cloud application used by the user (e. |
| Netskope.Alert.appcategory | String | Application Category as designated by Netskope. |
| Netskope.Alert.dlp_file | String | File/Object name extracted from the file/object. |
| Netskope.Alert.dlp_profile | String | DLP profile name. |
| Netskope.Alert.dlp_rule | String | DLP rule that triggered. |
| Netskope.Alert.category | String | The alert category. |
| Netskope.Alert.cci | Number | The cloud confidence index. |
Command example
!netskope-alert-list limit=1 start_time=2021-03-21T18:48:02.358736 end_time=2022-03-21T18:48:02.358736
Context Example
{
"Netskope": {
"Alert": {
"_insertion_epoch_timestamp": 1647888457,
"access_method": "API Connector",
"acked": "false",
"action": "alert",
"activity": "Introspection Scan",
"alert": "yes",
"alert_id": "0d7fa7e3cb3034bcc0ff94a5",
"alert_name": "Gdrive - Alert on PII",
"alert_type": "DLP",
"app": "Google Drive",
"appcategory": "Cloud Storage",
"browser": "unknown",
"category": "Cloud Storage",
"cci": 91,
"ccl": "excellent",
"count": 1,
"device": "Other",
"dlp_file": "CS Owned PC Data",
"dlp_incident_id": 1407319677213026800,
"dlp_is_unique_count": "true",
"dlp_parent_id": 1407319677213026800,
"dlp_profile": "Best Practice PII DLP Profile",
"dlp_rule": "FullName-Near-SSN-Unique",
"dlp_rule_count": 64,
"dlp_rule_severity": "High",
"dlp_unique_count": 63,
"dst_country": "US",
"dst_latitude": 37.4059906006,
"dst_location": "Mountain View",
"dst_longitude": -122.0785140991,
"dst_region": "California",
"dst_timezone": "America/Los_Angeles",
"dst_zipcode": "N/A",
"dstip": "142.250.191.78",
"exposure": "internal",
"file_lang": "ENGLISH",
"file_path": "/My Drive/CS Owned PC Data",
"file_size": 805733,
"file_type": "application/vnd.google-apps.spreadsheet",
"from_user": "test@goxsoar.com",
"instance": "goxsoar.com",
"instance_id": "goxsoar.com",
"internal_collaborator_count": 20,
"md5": "81e5926346f19f158688ccf40d88436e",
"mime_type": "application/vnd.google-apps.spreadsheet",
"modified": 1647888385,
"netskope_pop": "US-SJC1",
"object": "CS Owned PC Data",
"object_id": "1wxnfr3SWylRdPx8R3WHo2ywml7LsYPSt_6wqUX2KuDU",
"object_type": "File",
"organization_unit": "",
"os": "unknown",
"other_categories": [],
"outer_doc_type": 361,
"owner": "test@goxsoar.com",
"policy": "Gdrive - Alert on PII",
"request_id": 6525954495577788000,
"scan_type": "Ongoing",
"sha256": "3f53dac4dbce5fbc982ba3180b1b5d5fbed2a9c1cacf906471ce6a9aeef08a05",
"shared_with": "support@goxsoar.com",
"site": "Google Drive",
"suppression_key": "CS Owned PC Data",
"timestamp": 1647888450,
"title": "CS Owned PC Data",
"total_collaborator_count": 20,
"traffic_type": "CloudApp",
"true_obj_category": "Spreadsheet",
"true_obj_type": "Microsoft Excel 2007 XML",
"type": "nspolicy",
"ur_normalized": "test@goxsoar.com",
"url": "https://drive.google.com/open?id=4wxnfr3SWylRdPx8R3WHo2ywml7LsYPSt_6wqUX2KuDU",
"user": "test@goxsoar.com",
"user_id": "test@goxsoar.com",
"userkey": "test@goxsoar.com"
}
}
}
Human Readable Output
Alerts List
Current page size: 1
Showing page 1 out of others that may exist.
Alert Id Alert Name Alert Type Timestamp Action 0d7fa7e3cb3034bcc0ff94a5 Gdrive - Alert on PII DLP 1647888450 alert
netskope-quarantined-file-list
List all quarantined files.
Base Command
netskope-quarantined-file-list
Input
| Argument Name | Description | Required |
|---|---|---|
| start_time | Get files last modified after the provided date string. | Optional |
| end_time | Get files last modified before the provided date string. | Optional |
| limit | The maximum amount of clients to retrieve. Default is 50. | Optional |
| page | The page number of the clients to retrieve (minimum is 1). Default is 1. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Netskope.Quarantine.quarantine_profile_id | String | The ID of quarantine profile. |
| Netskope.Quarantine.quarantine_profile_name | String | The name of quarantine profile. |
| Netskope.Quarantine.file_id | String | The ID of the quarantined file. |
| Netskope.Quarantine.original_file_name | String | The original filename before quarantining. |
| Netskope.Quarantine.policy | String | The policy name caused quarantine the file. |
| Netskope.Quarantine.quarantined_file_name | String | The filename after quarantining. |
| Netskope.Quarantine.user_id | String | The ID of the user related to the quarantined file. |
Command example
!netskope-quarantined-file-list limit=1
Context Example
{
"Netskope": {
"Quarantine": {
"file_id": "1M_RU4jLPUwclKOhqZ7sPSqkMNS-S6Vyr",
"original_file_name": "PII SSN Large v2.xlsx",
"policy": "[Data Protection] - Quarantine PII Uploads to Box",
"quarantine_profile_id": "1",
"quarantine_profile_name": "Qmasters Testing Google Drive",
"quarantined_file_name": "inline_884993759783_1_F2DD7F63_PII SSN Large v2.xlsx",
"user_id": "test@goxsoar.com"
}
}
}
Human Readable Output
Quarantined Files List
Current page size: 1
Showing page 1 out of others that may exist.
quarantine_profile_id quarantine_profile_name file_id original_file_name policy 1 Qmasters Testing Google Drive 1M_RU4jLPUwclKOhqZ7sPSqkMNS-S6Vyr PII SSN Large v2.xlsx [Data Protection] - Quarantine PII Uploads to Box
netskope-quarantined-file-get
Download a quarantined file.
Base Command
netskope-quarantined-file-get
Input
| Argument Name | Description | Required |
|---|---|---|
| quarantine_profile_id | The ID of quarantine profile. | Required |
| file_id | The ID of the quarantined file. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| File.Size | Number | The size of the file. |
| File.Name | String | The name of the file. |
| File.EntryID | String | The entry ID of the file. |
| File.Info | String | File information. |
| File.Type | String | The file type. |
| File.Extension | String | The file extension. |
Command example
!netskope-quarantined-file-get file_id=1M_RU4jLPUwclKOhqZ7sPSqkMNS-S6Vyr quarantine_profile_id=1
Context Example
{
"File": {
"EntryID": "4447@8479e914-8493-4968-8f32-78852375d17b",
"Extension": "zip",
"Info": "application/zip",
"MD5": "8ac692ef2cc78adfc523188e54d52933",
"Name": "1M_RU4jLPUwclKOhqZ7sPSqkMNS-S6Vyr.zip",
"SHA1": "19cf128ad8fd41108d0a601e8e9c8cf123c11c5a",
"SHA256": "9ea98de9c4f852665f678338767280f64b20ed11943c49709440643ed04df122",
"SHA512": "5a6bce0fd15e4184d29ee8d38627ec47150665a6ccb67d39b02a8898ff0c987c4e7be580c9243cc3d4a7f3f2b637f226216434bf01bc2babfe35a4b7ff8cc2cc",
"SSDeep": "384:wc313ff+IizBt/oPervm6X61XWRcjDQJB9k3Wl:wMGIct/PjtX61EVB9mWl",
"Size": 15774,
"Type": "Microsoft Excel 2007+"
}
}
Human Readable Output
netskope-quarantined-file-update
Take an action on a quarantined file.
Base Command
netskope-quarantined-file-update
Input
| Argument Name | Description | Required |
|---|---|---|
| quarantine_profile_id | The profile ID of the quarantined file. | Required |
| file_id | The ID of the quarantined file. | Required |
| action | Action to be performed on a quarantined. Possible values are: block, allow. | Required |
Context Output
There is no context output for this command.
Command example
!netskope-quarantined-file-update file_id=1M_RR4jLPUwclKOhqZ7sPSqkMNS-S6Vyr quarantine_profile_id=1 action=block
Human Readable Output
The file 1M_RR4jLPUwclKOhqZ7sPSqkMNS-S6Vyr was successfully blocked!
netskope-url-list-update
Update the URL List with the values provided.
The command will override the whole list content, rather than appending the new values.
Base Command
netskope-url-list-update
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of an existing URL List shown in the Netskope UI on the URL List page. | Required |
| urls | The content of the URL list. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Netskope.URLList.name | String | The name of the URL list. |
| Netskope.URLList.URL | String | The content the URL list. |
Command example
!netskope-url-list-update name="Allowed URLs" urls="allow.me,allow2.me"
Context Example
{
"Netskope": {
"URLList": {
"URL": [
"allow.me",
"allow2.me"
],
"name": "Allowed URLs"
}
}
}
Human Readable Output
URL List Allowed URLs:
allow.me, allow2.me
netskope-file-hash-list-update
Update file hash list with the values provided.
The command will override the whole list content, rather than appending the new values.
Base Command
netskope-file-hash-list-update
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of an existing file hash list shown in the Netskope UI on the file hash list page. | Required |
| hash | List of file hashes (md5 or sha256). | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| FileHashList.name | String | The name of the hash list. |
| FileHashList.hash | String | The content of the hash list. |
Command example
!netskope-file-hash-list-update name="Test SHA256" hash="00db7cf5cc13df9ae88615af999582608361c14fc915d1dd76fa619d1c341597"
Context Example
{
"Netskope": {
"FileHashList": {
"hash": [
"00db7cf5cc13df9ae88615af999582608361c14fc915d1dd76fa619d1c341597"
],
"name": "Test SHA256"
}
}
}
Human Readable Output
Hash List Test SHA256:
00db7cf5cc13df9ae88615af999582608361c14fc915d1dd76fa619d1c341597
netskope-client-list
Get information about the Netskope clients.
Base Command
netskope-client-list
Input
| Argument Name | Description | Required |
|---|---|---|
| query | Free query on the clients, based on the client fields. For example, “host_info.hostname eq xxx”. For more information, please visit Netskope documentation: https://docs.netskope.com/en/get-client-data.html’. | Optional |
| limit | The maximum amount of clients to retrieve. Default is 50. | Optional |
| page | The page number of the clients to retrieve (minimum is 1). Default is 1. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Netskope.Client.client_id | String | The ID of the Netskope client. |
| Netskope.Client.client_version | String | The client version. |
| Netskope.Client.device_id | String | The ID of the client’s device. |
| Netskope.Client.host_info | String | Information about the client’s host. |
| Netskope.Client.last_event | String | Information about the last event related to the client. |
| Netskope.Client.user_added_time | String | The last time a client’s user was added to Netskope. |
| Netskope.Client.users | String | List of all users of the provided client. |
Command example
!netskope-client-list limit=1
Context Example
{
"Netskope": {
"Client": {
"client_id": "TEST82A5",
"client_version": "91.0.6.812",
"device_id": "TEST82A5",
"host_info": {
"device_make": "Parallels Software International Inc.",
"device_model": "Parallels Virtual Platform",
"hostname": "TEST82A5",
"managementID": "",
"nsdeviceuid": "725DAC1A-6654-3F3A-971E-C984FBE9FE5E",
"os": "Windows",
"os_version": "10.0 (2009)"
},
"last_event": {
"actor": "System",
"event": "Tunnel Up",
"npa_status": "Steering Disabled",
"status": "Enabled",
"timestamp": 1642475967
},
"user_added_time": 1638994653,
"users": [
{
"_id": "0c6f3f867882c2d243a83310",
"device_classification_status": "Not Configured",
"last_event": {
"actor": "System",
"event": "Tunnel Up",
"npa_status": "Steering Disabled",
"status": "Enabled",
"timestamp": 1642475967
},
"user_source": "Manual",
"user_state": 0,
"userkey": "W1Acv9LP05u2654lwRaD",
"username": "test@goxsoar.com"
},
{
"_id": "0c6f3f867882c2d243a83310",
"device_classification_status": "Unknown",
"last_event": {
"actor": "System",
"event": "Tunnel Down",
"npa_status": "Disabled",
"status": "Disabled",
"timestamp": 1638995110
},
"userkey": "W1Acv9LP05u2654lwRaD"
}
]
}
}
}
Human Readable Output
Clients List
Current page size: 1
Showing page 1 out of others that may exist.
Client Id Client Version Device Id User Added Time TEST82A5 91.0.6.812 TEST82A5 1638994653
netskope-host-associated-user-list
List all users of certain host by its hostname.
Base Command
netskope-host-associated-user-list
Input
| Argument Name | Description | Required |
|---|---|---|
| hostname | The hostname to view its users. | Required |
| limit | The maximum amount of users to retrieve. Default is 50. | Optional |
| page | The page number of the users to retrieve (minimum is 1). Default is 1. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Netskope.User.user_id | String | The ID of the Netskope user. |
| Netskope.User.device_classification_status | String | The device classification status. |
| Netskope.User.last_event | Unknown | Information about the last event related to the user. |
| Netskope.User.user_source | String | The source of the user. |
| Netskope.User.userkey | String | The user key. |
| Netskope.User.username | String | The name/email of the user. |
Command example
!netskope-host-associated-user-list hostname=TEST82A5 limit=1
Context Example
{
"Netskope": {
"User": {
"device_classification_status": "Unknown",
"last_event": {
"actor": "System",
"event": "Tunnel Down",
"npa_status": "Disabled",
"status": "Disabled",
"timestamp": 1638995110
},
"user_id": "0c6f3f867882c2d243a83310",
"user_source": "Manual",
"user_state": 0,
"userkey": "W1Acv9LP05u2654lwRaD",
"username": "test@goxsoar.com"
}
}
}
Human Readable Output
Users Associated With TEST82A5
Current page size: 1
Showing page 1 out of others that may exist.
user_id username user_source 0c6f3f867882c2d243a83310 test@goxsoar.com Manual 0c6f3f867882c2d243a83310
netskope-user-associated-host-list
List all hosts related to a certain username.
Base Command
netskope-user-associated-host-list
Input
| Argument Name | Description | Required |
|---|---|---|
| username | The username to view its hosts. | Required |
| limit | The maximum amount of hosts to retrieve. Default is 50. | Optional |
| page | The page number of the hosts to retrieve (minimum is 1). Default is 1. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Netskope.Host.nsdeviceuid | String | Netskope device UID. |
| Netskope.Host.os | String | The device operating system. |
| Netskope.Host.os_version | String | The device operating system version. |
| Netskope.Host.device_model | String | The device model. |
| Netskope.Host.hostname | String | The hostname of the device. |
| Netskope.Host.agent_status | String | The status of the agent on the device. |
Command example
!netskope-user-associated-host-list username=test@goxsoar.com
Context Example
{
"Netskope": {
"Host": {
"agent_status": "Enabled",
"device_make": "Parallels Software International Inc.",
"device_model": "Parallels Virtual Platform",
"hostname": "TEST82A5",
"managementID": "",
"nsdeviceuid": "725DAC1A-6654-3F3A-971E-C984FBE9FE5E",
"os": "Windows",
"os_version": "10.0 (2009)"
}
}
}
Human Readable Output
Hosts Associated With test@goxsoar.com
Current page size: 50
Showing page 1 out of others that may exist.
hostname os_version agent_status TEST82A5 10.0 (2009) Enabled
Configuration parameters
url— Server URL (required)credentials— (required)max_fetch— Maximum incidents per fetch. Max value is 200. (required)first_fetch— First fetch timestamp (<number> <time unit>, like 12 hours, 7 days)alerts_query— Alerts Queryfetch_events— Fetch Eventsevent_types— Event types to fetch.max_events_fetch— Maximum events as incidents per fetch. Max value is 200.events_query— Events QueryincidentType— Incident typeincidentFetchInterval— Incidents Fetch IntervalisFetch— Fetch incidentsinsecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (10)
-
netskope-alert-listGet alerts generated by Netskope, including policy, DLP, and watch list alerts. You must provide start_time and end_time, or insertion_start_time and insertion_end_time, or timeperiod. Also, you cannot provide a combination of the options mentioned above.
-
netskope-client-listGet information about the Netskope clients.
-
netskope-event-listGet events extracted from SaaS traffic and or logs. You must provide start_time and end_time, or insertion_start_time and insertion_end_time, or timeperiod. Also, you cannot provide a combination of the options mentioned above.
-
netskope-file-hash-list-updateUpdate file hash list with the values provided. The command will override the whole list content, rather than appending the new values.
-
netskope-host-associated-user-listList all users of certain host by its hostname.
-
netskope-quarantined-file-getDownload a quarantined file.
-
netskope-quarantined-file-listList all quarantined files.
-
netskope-quarantined-file-updateTake an action on a quarantined file.
-
netskope-url-list-updateUpdate the URL List with the values provided. The command will override the whole list content, rather than appending the new values.
-
netskope-user-associated-host-listList all hosts related to a certain username.
from copy import deepcopy from typing import Any import demistomock as demisto # noqa: F401 import urllib3 from CommonServerPython import * # noqa: F401 from CommonServerUserPython import * # disable insecure warnings urllib3.disable_warnings() DEFAULT_PAGE = 1 DEFAULT_LIMIT = 50 DEFAULT_MAX_FETCH = DEFAULT_LIMIT DEFAULT_EVENTS_FETCH = DEFAULT_LIMIT DEFAULT_EVENT_TYPE = "application" DEFAULT_FIRST_FETCH = "7 days" MAX_LIMIT = 100 MAX_FETCH = 200 MAX_EVENTS_FETCH = 200 TIME_PERIOD_MAPPING = { "Last 60 Minutes": 3600, "Last 24 Hours": 86400, "Last 7 Days": 604800, "Last 30 Days": 2592000, "Last 60 Days": 5184000, "Last 90 Days": 7776000, } class Client(BaseClient): """ Client for Netskope RESTful API. Args: base_url (str): The base URL of Netskope. token (str): The token to authenticate against Netskope API. use_ssl (bool): Specifies whether to verify the SSL certificate or not. use_proxy (bool): Specifies if to use XSOAR proxy settings. """ def __init__(self, base_url: str, token: str, use_ssl: bool, use_proxy: bool): super().__init__(urljoin(base_url, "/api/v1/"), verify=use_ssl, proxy=use_proxy) self._session.params["token"] = token # type: ignore def list_events_request( self, query: str | None = None, event_type: str | None = None, timeperiod: int | None = None, start_time: int | None = None, end_time: int | None = None, insertion_start_time: int | None = None, insertion_end_time: int | None = None, limit: int | None = None, skip: int | None = None, unsorted: bool | None = None, ) -> dict[str, Any]: """ Get events extracted from SaaS traffic and or logs. Args: query (Optional[str]): Free query to filter the events. event_type (Optional[str]): Select events by their type. timeperiod (Optional[int]): Get all events from a certain time period. start_time (Optional[int]): Restrict events to those that have timestamps greater than the provided timestamp. end_time (Optional[int]): Restrict events to those that have timestamps less than or equal to the provided timestamp. insertion_start_time (Optional[int]): Restrict events to those that were inserted to the system after the provided timestamp. insertion_end_time (Optional[int]): Restrict events to those that were inserted to the system before the provided timestamp. limit (Optional[int]): The maximum amount of events to retrieve (up to 10000 events). skip (Optional[int]): The skip number of the events to retrieve (minimum is 1). unsorted (Optional[bool]): If true, the returned data will not be sorted (useful for improved performance). Returns: Dict[str, Any]: Netskope events. """ body = remove_empty_elements( { "query": query, "type": event_type, "timeperiod": timeperiod, "starttime": start_time, "endtime": end_time, "insertionstarttime": insertion_start_time, "insertionendtime": insertion_end_time, "limit": limit, "skip": skip, "unsorted": unsorted, } ) return self._http_request(method="POST", url_suffix="events", json_data=body) def list_alerts_request( self, query: str | None = None, alert_type: str | None = None, acked: bool | None = None, timeperiod: int | None = None, start_time: int | None = None, end_time: int | None = None, insertion_start_time: int | None = None, insertion_end_time: int | None = None, limit: int | None = None, skip: int | None = None, unsorted: bool | None = None, ) -> dict[str, Any]: """ Get alerts generated by Netskope, including policy, DLP, and watch list alerts. Args: query (Optional[str]): Free query to filter the alerts. alert_type (Optional[str]): Select alerts by their type. acked (Optional[bool]): Whether to retrieve acknowledged alerts or not. timeperiod (Optional[int]): Get alerts from certain time period. start_time (Optional[int]): Restrict alerts to those that have timestamps greater than the provided timestamp. end_time (Optional[int]): Restrict alerts to those that have timestamps less than or equal to the provided timestamp. insertion_start_time (Optional[int]): Restrict alerts which have been inserted into the system after the provided timestamp. insertion_end_time (Optional[int]): Restrict alerts which have been inserted into the system before the provided timestamp. limit (Optional[int]): The maximum number of alerts to return (up to 10000). skip (Optional[int]): The skip number of the alerts to retrieve (minimum is 1). unsorted (Optional[bool]): If true, the returned data will not be sorted (useful for improved performance). Returns: Dict[str, Any]: Netskope alerts. """ body = remove_empty_elements( { "query": query, "alert_type": alert_type, "acked": acked, "timeperiod": timeperiod, "starttime": start_time, "endtime": end_time, "insertionstarttime": insertion_start_time, "insertionendtime": insertion_end_time, "limit": limit, "skip": skip, "unsorted": unsorted, } ) return self._http_request(method="POST", url_suffix="alerts", json_data=body) def list_quarantined_files_request( self, start_time: int | None = None, end_time: int | None = None, limit: int | None = None, skip: int | None = None ) -> dict[str, Any]: """ List all quarantined files. Args: start_time (Optional[int]): Get files last modified within a certain time period. end_time (Optional[int]): Get files last modified within a certain time period. limit (Optional[int]): The maximum amount of clients to retrieve (up to 10000). skip (Optional[int]): The skip number of the clients to retrieve (minimum is 1). Returns: Dict[str, Any]: Netskope quarantine files. """ body = remove_empty_elements( {"starttime": start_time, "endtime": end_time, "limit": limit, "skip": skip, "op": "get-files"} ) return self._http_request(method="POST", url_suffix="quarantine", json_data=body) def get_quarantined_file_request(self, quarantine_profile_id: str, file_id: str) -> bytes: """ Download a quarantined file. Args: quarantine_profile_id (str): The ID of quarantine profile. file_id (str): The ID of the quarantined file. Returns: bytes: The quarantined file content. """ body = {"quarantine_profile_id": quarantine_profile_id, "file_id": file_id, "op": "download-url"} return self._http_request(method="POST", url_suffix="quarantine", json_data=body, resp_type="content") def update_quarantined_file_request(self, quarantine_profile_id: str, file_id: str, action: str) -> None: """ Take an action on a quarantined file. Args: quarantine_profile_id (str): The profile id of the quarantined file. file_id (str): The id of the quarantined file. action (str): Action to be performed on a quarantined. """ body = {"quarantine_profile_id": quarantine_profile_id, "file_id": file_id, "action": action, "op": "take-action"} self._http_request(method="POST", url_suffix="quarantine", json_data=body, resp_type="text") def update_url_list_request(self, name: str, urls: list[str]) -> None: """ Update the URL List with the values provided. Args: name (str): Name of an existing URL List shown in the Netskope UI on the URL List skip. urls (List[str]): The content of the URL list. """ body = {"name": name, "list": ",".join(urls)} self._http_request(method="POST", url_suffix="updateUrlList", json_data=body) def update_file_hash_list_request(self, name: str, hashes: list[str]) -> None: """ Update file hash list with the values provided. Args: name (str): Name of an existing file hash list shown in the Netskope UI on the file hash list skip. hashes (str): List of file hashes (md5 or sha256). """ body = {"name": name, "list": ",".join(hashes)} return self._http_request(method="POST", url_suffix="updateFileHashList", json_data=body) def list_clients_request(self, query: str | None = None, limit: int | None = None, skip: int | None = None) -> dict[str, Any]: """ Get information about the Netskope clients. Args: query (Optional[str]): Free query on the clients, based on the client fields. limit (Optional[int]): The maximum amount of clients to retrieve (up to 10000). skip (Optional[int]): The skip number of the clients to retrieve (minimum is 1). Returns: Dict[str, Any]: The clients information. """ body = remove_empty_elements({"query": query, "limit": limit, "skip": skip}) return self._http_request(method="POST", url_suffix="clients", params=body) def _http_request(self, *args, **kwargs): response = super()._http_request(*args, **kwargs) if isinstance(response, dict) and "errors" in response: errors = "\n".join(response["errors"]) raise DemistoException(f"Invalid API call: {errors}", res=response) return response def arg_to_boolean(arg: str | None) -> bool | None: """ Converts an XSOAR argument to a Python boolean or None. Args: arg (Optional[str]): The argument to convert. Returns: Optional[bool]: A boolean if arg can be converted, or None if arg is None. """ if arg is None: return None return argToBoolean(arg) def arg_to_seconds_timestamp(arg: str | None): """ Converts an XSOAR date string argument to a timestamp in seconds. Args: arg (Optional[str]): The argument to convert. Returns: Optional[int]: A timestamp if arg can be converted, or None if arg is None. """ if arg is None: return None return date_to_seconds_timestamp(arg_to_datetime(arg)) # type: ignore def date_to_seconds_timestamp(date_str_or_dt: Union[str, datetime]) -> int: """ Converts date string or datetime object to a timestamp in seconds. Args: date_str_or_dt (Union[str, datetime]): The datestring or datetime. Returns: int: The timestamp in seconds. """ return date_to_timestamp(date_str_or_dt) // 1000 def validate_time_arguments( start_time: int | None = None, end_time: int | None = None, insertion_start_time: int | None = None, insertion_end_time: int | None = None, timeperiod: int | None = None, ) -> None: """ Validates time arguments from the user. The user must provide one of the following: - start_time and end_time. - insertion_start_time and insertion_end_time. - timeperiod. Args: start_time (Optional[int], optional): The start time to fetch from the API. end_time (Optional[int], optional): The end time to fetch from the API. insertion_start_time (Optional[int], optional): The insertion start time to fetch from the API. insertion_end_time (Optional[int], optional): The insertion end time to fetch from the API. timeperiod (Optional[str], optional): The timeperiod to fetch from the API. Raises: DemistoException: The user did not provide valid timestamp. """ combination = (all((start_time, end_time)), all((insertion_start_time, insertion_end_time)), bool(timeperiod)) if not any(combination): raise DemistoException( "Missing time arguments. Please provide start_time and end_time, " "or insertion_start_time and or insertion_end_time or timeperiod." ) if combination.count(True) > 1: raise DemistoException( "Invalid time arguments. Please provide only start_time and end_time, " "or insertion_start_time and or insertion_end_time or timeperiod. " "You must not combine between the mentioned options." ) def validate_fetch_params( max_fetch: int, max_events_fetch: int, fetch_events: bool, first_fetch: str, event_types: list[str] ) -> None: """ Validates the parameters for fetch incident command. Args: max_fetch: (int): The maximum number of incidents for one fetch. max_events_fetch (int) The maximum number of events per incident for one fetch. fetch_events (bool): Whether or not fetch events when fetching incident. first_fetch: (str): First fetch time in words. """ if first_fetch: arg_to_datetime(first_fetch) # verify that it is a date. if max_fetch > MAX_FETCH: return_error(f"The Maximum number of incidents per fetch should not exceed {MAX_FETCH}.") if fetch_events and max_events_fetch > MAX_EVENTS_FETCH: return_error(f"The Maximum number of events for each incident per fetch should not exceed {MAX_EVENTS_FETCH}.") if not isinstance(event_types, list): return_error("The fetched event types must be a list.") def get_pagination_readable_message(header: str, page: int, limit: int) -> str: return f"{header}\n Current page size: {limit}\n Showing page {page} out of others that may exist." def get_pagination_arguments(args: dict[str, Any]) -> tuple[int, int, int]: """ Gets and validates pagination arguments for client (skip and limit). Args: args (Dict[str, Any]): The command arguments (page and limit). Returns: Tuple[int, int]: The page, calculated skip and limit after validation. """ page = arg_to_number(args.get("page")) or DEFAULT_PAGE limit = arg_to_number(args.get("limit")) or DEFAULT_LIMIT if page < 1: raise DemistoException("Page argument must be greater than 1") if not 1 <= limit <= MAX_LIMIT: raise DemistoException(f"Limit argument must be between 1 to {MAX_LIMIT}") return page, (page - 1) * limit, limit def list_events_command(client: Client, args: dict[str, str]) -> CommandResults: """ Get events extracted from SaaS traffic and or logs. Args: client (client): The Netskope client. args (Dict[str, Any]): Command arguments from XSOAR. Returns: CommandResults: Command results with raw response, outputs and readable outputs. """ query = args.get("query") event_type = args["event_type"] timeperiod = TIME_PERIOD_MAPPING.get(args.get("timeperiod", "")) start_time = arg_to_seconds_timestamp(args.get("start_time")) end_time = arg_to_seconds_timestamp(args.get("end_time")) insertion_start_time = arg_to_seconds_timestamp(args.get("insertion_start_time")) insertion_end_time = arg_to_seconds_timestamp(args.get("insertion_end_time")) page, skip, limit = get_pagination_arguments(args) unsorted = arg_to_boolean(args.get("unsorted")) validate_time_arguments( start_time=start_time, end_time=end_time, timeperiod=timeperiod, insertion_start_time=insertion_start_time, insertion_end_time=insertion_end_time, ) response = client.list_events_request( query=query, event_type=event_type, timeperiod=timeperiod, start_time=start_time, end_time=end_time, insertion_start_time=insertion_start_time, insertion_end_time=insertion_end_time, limit=limit, skip=skip, unsorted=unsorted, ) outputs = deepcopy(response["data"]) for event in outputs: event["event_id"] = event["_id"] event["timestamp"] = timestamp_to_datestring(event["timestamp"] * 1000) readable_output = tableToMarkdown( get_pagination_readable_message("Events List:", page=page, limit=limit), outputs, removeNull=True, headers=["event_id", "timestamp", "type", "access_method", "app", "traffic_type"], headerTransform=string_to_table_header, ) return CommandResults( outputs_prefix="Netskope.Event", outputs_key_field="event_id", outputs=outputs, readable_output=readable_output, raw_response=response, ) def list_alerts_command(client: Client, args: dict[str, str]) -> CommandResults: """ Get alerts generated by Netskope, including policy, DLP, and watch list alerts. Args: client (client): The Netskope client. args (Dict[str, Any]): Command arguments from XSOAR. Returns: CommandResults: Command results with raw response, outputs and readable outputs. """ query = args.get("query") alert_type = args.get("alert_type") acked = arg_to_boolean(args.get("acked")) timeperiod = TIME_PERIOD_MAPPING.get(args.get("timeperiod", "")) start_time = arg_to_seconds_timestamp(args.get("start_time")) end_time = arg_to_seconds_timestamp(args.get("end_time")) insertion_start_time = arg_to_seconds_timestamp(args.get("insertion_start_time")) insertion_end_time = arg_to_seconds_timestamp(args.get("insertion_end_time")) page, skip, limit = get_pagination_arguments(args) unsorted = arg_to_boolean(args.get("unsorted")) validate_time_arguments( start_time=start_time, end_time=end_time, timeperiod=timeperiod, insertion_start_time=insertion_start_time, insertion_end_time=insertion_end_time, ) response = client.list_alerts_request( query=query, alert_type=alert_type, acked=acked, timeperiod=timeperiod, start_time=start_time, end_time=end_time, insertion_start_time=insertion_start_time, insertion_end_time=insertion_end_time, limit=limit, skip=skip, unsorted=unsorted, ) outputs = deepcopy(response["data"]) for alert in outputs: alert["alert_id"] = alert["_id"] alert["timestamp"] = timestamp_to_datestring(alert["timestamp"] * 1000) readable_output = tableToMarkdown( get_pagination_readable_message("Alerts List:", page=page, limit=limit), outputs, removeNull=True, headers=["alert_id", "alert_name", "alert_type", "timestamp", "action"], headerTransform=string_to_table_header, ) return CommandResults( outputs_prefix="Netskope.Alert", outputs_key_field="alert_id", outputs=outputs, readable_output=readable_output, raw_response=response, ) def list_quarantined_files_command(client: Client, args: dict[str, str]) -> CommandResults: """ List all quarantined files. Args: client (client): The Netskope client. args (Dict[str, Any]): Command arguments from XSOAR. Returns: CommandResults: Command results with raw response, outputs and readable outputs. """ start_time = arg_to_seconds_timestamp(args.get("start_time")) end_time = arg_to_seconds_timestamp(args.get("end_time")) page, skip, limit = get_pagination_arguments(args) response = client.list_quarantined_files_request(start_time=start_time, end_time=end_time, limit=limit, skip=skip) outputs = dict_safe_get(response, ["data", "quarantined"]) # type: ignore for output in outputs: # type: ignore for file_output in output["files"]: file_output["quarantine_profile_id"] = output["quarantine_profile_id"] file_output["quarantine_profile_name"] = output["quarantine_profile_name"] outputs: list = sum((output["files"] for output in outputs), []) readable_header = get_pagination_readable_message("Quarantined Files List:", page=page, limit=limit) readable_output = tableToMarkdown( readable_header, outputs, removeNull=True, headers=["quarantine_profile_id", "quarantine_profile_name", "file_id", "original_file_name", "policy"], headerTransform=string_to_table_header, ) return CommandResults( outputs_prefix="Netskope.Quarantine", outputs_key_field="file_id", outputs=outputs, readable_output=readable_output, raw_response=response, ) def get_quarantined_file_command(client: Client, args: dict[str, str]) -> CommandResults: """ Download a quarantined file. Args: client (client): The Netskope client. args (Dict[str, Any]): Command arguments from XSOAR. Returns: CommandResults: Command results with raw response, outputs and readable outputs. """ quarantine_profile_id = args["quarantine_profile_id"] file_id = args["file_id"] file_name = args.get("file_name", file_id) response = client.get_quarantined_file_request(quarantine_profile_id=quarantine_profile_id, file_id=file_id) return fileResult(filename=file_name, data=response, file_type=EntryType.FILE) def update_quarantined_file_command(client: Client, args: dict[str, str]) -> CommandResults: """ Take an action on a quarantined file. Args: client (client): The Netskope client. args (Dict[str, Any]): Command arguments from XSOAR. Returns: CommandResults: Command results with raw response, outputs and readable outputs. """ quarantine_profile_id = args["quarantine_profile_id"] file_id = args["file_id"] action = args["action"] client.update_quarantined_file_request(quarantine_profile_id=quarantine_profile_id, file_id=file_id, action=action) readable_output = f"## The file {file_id} was successfully {action}ed!" return CommandResults(readable_output=readable_output) def update_url_list_command(client: Client, args: dict[str, str]) -> CommandResults: """ Update the URL List with the values provided. Args: client (client): The Netskope client. args (Dict[str, Any]): Command arguments from XSOAR. Returns: CommandResults: Command results with raw response, outputs and readable outputs. """ name = args["name"] urls = argToList(args["urls"]) client.update_url_list_request(name=name, urls=urls) outputs = {"name": name, "URL": urls} readable_output = f'URL List {name}:\n{", ".join(urls)}' return CommandResults( outputs_prefix="Netskope.URLList", outputs_key_field="name", outputs=outputs, readable_output=readable_output ) def update_file_hash_list_command(client: Client, args: dict[str, str]) -> CommandResults: """ Update file hash list with the values provided. Args: client (client): The Netskope client. args (Dict[str, Any]): Command arguments from XSOAR. Returns: CommandResults: Command results with raw response, outputs and readable outputs. """ name = args.get("name", "") hashes = argToList(args.get("hash")) client.update_file_hash_list_request(name=name, hashes=hashes) outputs = {"name": name, "hash": hashes} readable_output = f'Hash List {name}:\n{", ".join(hashes)}' return CommandResults( outputs_prefix="Netskope.FileHashList", outputs_key_field="name", outputs=outputs, readable_output=readable_output ) def list_clients_command(client: Client, args: dict[str, str]) -> CommandResults: """ Get information about the Netskope clients. Args: client (client): The Netskope client. args (Dict[str, Any]): Command arguments from XSOAR. Returns: CommandResults: Command results with raw response, outputs and readable outputs. """ query = args.get("query") page, skip, limit = get_pagination_arguments(args) response = client.list_clients_request(query=query, limit=limit, skip=skip) outputs = [client["attributes"] for client in response["data"]] for output in outputs: output["client_id"] = output["_id"] readable_header = get_pagination_readable_message("Clients List:", page=page, limit=limit) readable_output = tableToMarkdown( readable_header, outputs, removeNull=True, headers=["client_id", "client_version", "device_id", "user_added_time"], headerTransform=string_to_table_header, ) return CommandResults( outputs_prefix="Netskope.Client", outputs_key_field="client_id", outputs=outputs, readable_output=readable_output, raw_response=response, ) def list_host_associated_user_command(client: Client, args: dict[str, str]) -> CommandResults: """ List all users of certain host by its hostname. Args: client (client): The Netskope client. args (Dict[str, Any]): Command arguments from XSOAR. Returns: CommandResults: Command results with raw response, outputs and readable outputs. """ hostname = args["hostname"] page, skip, limit = get_pagination_arguments(args) response = client.list_clients_request(query=f"host_info.hostname eq {hostname}", limit=limit, skip=skip) outputs: list = sum((client["attributes"].get("users") for client in response["data"]), []) for output in outputs: output["user_id"] = output["_id"] readable_header = get_pagination_readable_message(f"Users Associated With {hostname}:", page=page, limit=limit) readable_output = tableToMarkdown( readable_header, outputs, removeNull=True, headers=["user_id", "username", "user_source"], headerTransform=string_to_table_header, ) return CommandResults( outputs_prefix="Netskope.User", outputs_key_field="user_id", outputs=outputs, readable_output=readable_output, raw_response=response, ) def list_user_associated_host_command(client: Client, args: dict[str, str]) -> CommandResults: """ List all hosts related to a certain username. Args: client (client): The Netskope client. args (Dict[str, Any]): Command arguments from XSOAR. Returns: CommandResults: Command results with raw response, outputs and readable outputs. """ username = args["username"] page, skip, limit = get_pagination_arguments(args) response = client.list_clients_request(query=f"username eq {username}", limit=limit, skip=skip) outputs = [] for client in response["data"]: attributes = client["attributes"] agent_status = dict_safe_get(attributes, ["last_event", "status"]) outputs.append({"agent_status": agent_status, **attributes["host_info"]}) readable_header = get_pagination_readable_message(f"Hosts Associated With {username}:", page=page, limit=limit) readable_output = tableToMarkdown( readable_header, outputs, removeNull=True, headers=["hostname", "os_version", "agent_status"], headerTransform=string_to_table_header, ) return CommandResults( outputs_prefix="Netskope.Host", outputs_key_field="nsdeviceuid", outputs=outputs, readable_output=readable_output, raw_response=response, ) def test_module( client: Client, max_fetch: int, first_fetch: str, fetch_events: bool, max_events_fetch: int, event_types: list[str] ) -> str: """ Validates all integration parameters, and tests connection to Netskope instance. """ validate_fetch_params(max_fetch, max_events_fetch, fetch_events, first_fetch, event_types) client.list_alerts_request( limit=1, skip=0, start_time=date_to_seconds_timestamp(datetime.now()), end_time=date_to_seconds_timestamp(datetime.now()) ) return "ok" def fetch_multiple_type_events( client: Client, max_fetch: int, start_time: int, event_types: list[str], query: str | None ) -> list[dict[str, Any]]: """ Fetches events from multiple types. The function makes an API call for each type, since the API requires specifying the event type. Args: client (Client): The Netskope client. max_fetch (int): The maximum amount of events to fetch for each type. start_time (int): The time to fetch the events from. event_types (List[str]): The event types to fetch as incidents. query (Optional[str]): Query for filtering the events. Returns: List[Dict[str, Any]]: The fetched events. """ events = [] if event_types: max_fetch = max_fetch // len(event_types) for event_type in event_types: new_events = client.list_events_request( start_time=start_time, end_time=date_to_seconds_timestamp(datetime.now()), limit=max_fetch, unsorted=False, event_type=event_type, query=query, )["data"] for event in new_events: event["event_id"] = event["_id"] event["incident_type"] = event_type events.extend(new_events) return events def fetch_incidents( client: Client, max_fetch: int, first_fetch: str, fetch_events: bool, max_events_fetch: int, event_types: list[str], alerts_query: str | None, events_query: str | None, ) -> None: """ Fetches alerts and events as incidents. Args: client (Client): The Netskope client. max_fetch (int): Maximum number of incidents to fetch. first_fetch (str): The timestamp to fetch the incidents from. max_events_fetch (int): Maximum number of events to fetch. event_types (List[str]): The type of events to fetch. alerts_query (Optional[str]): Query for filtering the fetched alerts. events_query (Optional[str]): Query for filtering the fetched events. """ validate_fetch_params(max_fetch, max_events_fetch, fetch_events, first_fetch, event_types) last_run = demisto.getLastRun() or {} first_fetch: int = arg_to_seconds_timestamp(first_fetch) last_alert_time = last_run.get("last_alert_time") or first_fetch alerts = client.list_alerts_request( start_time=last_alert_time, end_time=date_to_seconds_timestamp(datetime.now()), limit=max_fetch, query=alerts_query, unsorted=False, )["data"] last_event_time = last_run.get("last_event_time") or first_fetch if fetch_events: events = fetch_multiple_type_events( client, max_fetch=max_events_fetch, start_time=last_event_time, event_types=event_types, query=events_query ) else: events = [] incidents = [] for alert in alerts: alert["incident_type"] = alert["alert_type"] incidents.append( {"name": alert["alert_name"], "occurred": timestamp_to_datestring(alert["timestamp"]), "rawJSON": json.dumps(alert)} ) for event in events: incidents.append( {"name": event["event_id"], "occurred": timestamp_to_datestring(event["timestamp"]), "rawJSON": json.dumps(event)} ) # The alerts and events are sorted in descending order. # Also, we increment the timestamp in one second to avoid duplicates. demisto.setLastRun( { "last_alert_time": alerts[0]["timestamp"] + 1 if alerts else last_alert_time, "last_event_time": events[0]["timestamp"] + 1 if events else last_event_time, } ) demisto.incidents(incidents) def main(): params = demisto.params() url = params["url"] token = params["credentials"]["password"] use_ssl = not params.get("insecure", False) use_proxy = params.get("proxy", False) max_fetch = arg_to_number(params.get("max_fetch")) or DEFAULT_MAX_FETCH first_fetch = params.get("first_fetch", DEFAULT_FIRST_FETCH) fetch_events = argToBoolean(params.get("fetch_events", False)) event_types = argToList(params.get("fetch_event_types", DEFAULT_EVENT_TYPE)) max_events_fetch = arg_to_number(params.get("max_events_fetch")) or DEFAULT_EVENTS_FETCH client = Client(url, token, use_ssl, use_proxy) commands = { "netskope-event-list": list_events_command, "netskope-alert-list": list_alerts_command, "netskope-quarantined-file-list": list_quarantined_files_command, "netskope-quarantined-file-get": get_quarantined_file_command, "netskope-quarantined-file-update": update_quarantined_file_command, "netskope-url-list-update": update_url_list_command, "netskope-file-hash-list-update": update_file_hash_list_command, "netskope-client-list": list_clients_command, "netskope-host-associated-user-list": list_host_associated_user_command, "netskope-user-associated-host-list": list_user_associated_host_command, } try: command = demisto.command() if command == "test-module": return_results( test_module( client, max_fetch=max_fetch, first_fetch=first_fetch, fetch_events=fetch_events, max_events_fetch=max_events_fetch, event_types=event_types, ) ) elif command == "fetch-incidents": fetch_incidents( client, max_fetch=max_fetch, first_fetch=first_fetch, fetch_events=fetch_events, max_events_fetch=max_events_fetch, event_types=event_types, alerts_query=demisto.params().get("alerts_query"), events_query=demisto.params().get("events_query"), ) elif command in commands: return_results(commands[command](client, demisto.args())) else: raise NotImplementedError(f"The command {command} does not exist!") except Exception as e: return_error(f"Failed to execute {demisto.command()} command.\nError:\n{e}") if __name__ in ("__main__", "__builtin__", "builtins"): main()