FortiSIEM
Search and update events of FortiSIEM and manage resource lists.
Analytics & SIEM · FortiSIEM
Details
| ID | FortiSIEM |
|---|---|
| Provider | Fortinet |
| Category | Analytics & SIEM |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
Use the FortiSIEM integration to search and update events and manage resource lists.
Use Cases
- Get alerts using different filters
- Maintain resource lists
- Close incidents
Configure FortiSIEM on Cortex XSOAR
- Navigate to Settings > Integrations > Servers & Services.
- Search for FortiSIEM.
- Click Add instance to create and configure a new integration instance.
- Name: a textual name for the integration instance.
- Fetch incidents
- Incident type
- Server URL (e.g.: https://192.168.0.1)
- Credentials
- Trust any certificate (not secure)
- Use system proxy settings
- 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.
- Get events by incident: fortisiem-get-events-by-incident
- Clear an incident: fortisiem-clear-incident
- Get events using a filter: fortisiem-get-events-by-filter
- Get device descriptions: fortisiem-get-cmdb-devices
- Get events using a query: fortisiem-get-events-by-query
- Get all resource lists: fortisiem-get-lists
- Add an element to a resource list: fortisiem-add-item-to-resource-list
- Remove an element from a resource list: fortisiem-remove-item-from-resource-list
- Get a list of all elements in a resource list: fortisiem-get-resource-list
1. Get events by incident
Gets events by incident.
Base Command
fortisiem-get-events-by-incident
Input
| Argument Name | Description | Required |
|---|---|---|
| incID | ID of the incident by which to filter. | Required |
| maxResults | Maximum number of results to return. | Optional |
| extendedData | Whether to extend the data. | Optional |
| maxWaitTime | Maximum time for the event report to finish (in seconds). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FortiSIEM.Events.EventType | string | Event type. |
| FortiSIEM.Events.EventID | string | FortiSIEM Event ID. |
| FortiSIEM.Events.RawEventLog | string | Raw Event Log. |
| FortiSIEM.Events.ReportingDevice | string | Reporting Device. |
| FortiSIEM.Events.IncidentID | number | Incident ID. |
| FortiSIEM.Events.User | string | Event User. |
| FortiSIEM.Events.EventReceiveTime | number | Event received timestamp. |
| FortiSIEM.Events.EventName | string | Event Name. |
| FortiSIEM.Events.ReportingIP | string | Reporting IP address. |
| FortiSIEM.Events.SystemEventCategory | string | System Event Category. |
| FortiSIEM.Events.EventAction | string | EventAction. |
| FortiSIEM.Events.RelayingIP | string | Relaying IP address. |
| FortiSIEM.Events.EventSeverityCategory | string | Severity Category. |
| FortiSIEM.Events.OrganizationName | string | Organization Name. |
| FortiSIEM.Events.ReportingVendor | string | Reporting Vendor. |
| FortiSIEM.Events.ReportingModel | string | Reporting Model. |
| FortiSIEM.Events.OrganizationName | string | Organization name. |
| FortiSIEM.Events.CollectorID | number | Collector ID. |
| FortiSIEM.Events.EventParserName | string | Name of raw event parser. |
| FortiSIEM.Events.HostIP | string | Host IP address. |
| FortiSIEM.Events.HostName | string | Host name. |
| FortiSIEM.Events.FileName | string | Name of the file associated with the event. |
| FortiSIEM.Events.ProcessName | string | Name of the process associated with the event. |
| FortiSIEM.Events.JobName | string | Name of the job associated with the event. |
| FortiSIEM.Events.Status | string | Event status. |
| FortiSIEM.Events.DestinationPort | string | Port of the traffic’s destination. |
| FortiSIEM.Events.SourcePort | string | Port of the traffic’s origin. |
| FortiSIEM.Events.DestinationIP | string | Destination IP address for the web. |
| FortiSIEM.Events.SourceIP | string | IP address of the traffic’s origin. The source varies by the direction: In HTTP requests, this is the web browser or other client. In HTTP responses, this is the physical server. |
| FortiSIEM.Events.ExtendedData | string | All additional data returned by FortiSIEM. |
| FortiSIEM.Events.DestinationInterface | string | Interface of the traffic’s destination. |
| FortiSIEM.Events.NATTranslation | string | NAT source port. |
| FortiSIEM.Events.Protocol | string | tcp: The protocol used by web traffic (tcp by default). |
| FortiSIEM.Events.SourceMAC | string | MAC address associated with the source IP address. |
| FortiSIEM.Events.NATIP | string | NAT source IP. |
Command Example
!fortisiem-get-events-by-incident incID=1919 maxResults=3
Context Example
{
"FortiSIEM.Events": [
{
"Destination Host Name": "google-public-dns-a.google.com",
"Event Name": "Permitted traffic flow started",
"Destination IP": "8.8.8.8",
"Incident ID": "1919",
"Source IP": "10.10.10.17",
"Raw Event Log": "<14>May 2 19:53:33 PA-Firewall 1,2019/05/02 19:53:33,007151000004733,TRAFFIC,start,2304,2019/05/02 19:53:33,10.100.100.17,8.8.8.8,80.80.80.146,8.8.8.8,Internet allow,,,dns,vsys1,Trust,Untrust,ethernet1/3,ethernet1/1,Forward to Fortisiem,2019/05/02 19:53:33,156575,1,57184,53,59686,53,0x400000,udp,allow,109,109,0,1,2019/05/02 19:53:31,0,any,0,32724731,0x0,10.0.0.0-10.255.255.255,United States,0,1,0,n/a,0,0,0,0,,PA-Firewall,from-policy,,,0,,0,,N/A,0,0,0,0,dcc8adba-6c1a-4eb1-9ac3-d0f33439ea67,0",
"Reporting IP": "10.100.100.254",
"Source TCP/UDP Port": "57184",
"IP Protocol": "17 (UDP)",
"ExtendedData": {
"1121": "HOST-10.100.100.17",
"1126": "Trust",
"1127": "Untrust",
"3061": "dns",
"3001": "",
"110": 10000,
"3008": "dns",
"24": "LOW",
"20": "Permitted traffic flow started",
"21": 1,
"1": "PAN-OS-TRAFFIC-start-allow",
"1038": 0,
"5": "0 (Permit)",
"8": "10.10.10.254",
"1010": "17 (UDP)",
"2422": "Google",
"1151": "allow",
"1150": "Internet allow",
"9": "10.10.10.254",
"2410": "United States",
"1004": "8.8.8.8",
"1002": "google-public-dns-a.google.com",
"1001": "8.8.8.8",
"1000": "10.10.10.17"
...
},
"Event Receive Time": 1556690013000,
"Event Type": "PAN-OS-TRAFFIC-start-allow",
"Destination TCP/UDP Port": "53 (DOMAIN)",
"Event ID": "8255801804490150940"
},
...
]
}
Human Readable Output
FortiSIEM events for Incident 1919
| Event Receive Time | Event Type | Event Name | Source IP | Destination IP | Destination Host Name | IP Protocol | Source TCP/UDP Port | Destination TCP/UDP Port | Reporting IP | Raw Event Log |
|---|---|---|---|---|---|---|---|---|---|---|
| 1556690013000 | PAN-OS-TRAFFIC-start-allow | Permitted traffic flow started | 10.10.10.17 | 8.8.8.8 | google-public-dns-a.google.com | 17 (UDP) | 57184 | 53 (DOMAIN) | 10.10.10.254 | <14>May 2 19:53:33 PA-Firewall 1,2019/05/02 19:53:33,007151000004733,TRAFFIC,start,2304,2019/05/01 09:53:33,10.100.100.17,8.8.8.8,80.227.43.146,8.8.8.8,Internet allow,dns,vsys1,Trust,Untrust,ethernet1/3,ethernet1/1,Forward to Fortisiem,2019/05/02 19:53:33,156575,1,57184,53,59686,53,0x400000,udp,allow,109,109,0,1,2019/05/02 19:53:31,0,any,0,32724731,0x0,10.0.0.0-10.255.255.255,United States,0,1,0,n/a,0,0,0,0,PA-Firewall,from-policy,0,0,N/A,0,0,0,0,dcc8adba-6c1a-4eb1-9ac3-d0f33439ea67,0 |
2. Clear an incident
Clear (close) a FortiSIEM incident.
Base Command
fortisiem-clear-incident
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | ID of the incident to close. | Required |
| close_reason | Reason for closing. | Optional |
Context Output
There is no context output for this command.
Command Example
!fortisiem-clear-incident incident_id=1919 close_reason="False Positive"
Human Readable Output
Incident cleared successfully.
3. Get events using a filter
Returns an event list according to the specified filters.
Base Command
fortisiem-get-events-by-filter
Input
| Argument Name | Description | Required |
|---|---|---|
| maxResults | Maximum number of results to return. | Optional |
| extendedData | Whether to extend the data. | Optional |
| maxWaitTime | Maximum time for the event report to finish (in seconds). | Optional |
| reptDevIpAddr | Reporting IP address. | Optional |
| destIpAddr | Destination IP address. | Optional |
| srcIpAddr | Source IP address. | Optional |
| destMACAddr | Destination MAC address. | Optional |
| srcMACAddr | Source MAC address. | Optional |
| destDomain | Destination domain. | Optional |
| srcDomain | Source domain. | Optional |
| destName | Destination name. | Optional |
| srcName | Source name. | Optional |
| destAction | Destination action. | Optional |
| destUser | Destination user. | Optional |
| reportWindow | Relative report time value. | Optional |
| reportWindowUnit | Relative report time unit. | Optional |
| eventType | Event type. | Optional |
| srcGeoCountry | Source geo country. | Optional |
| User | User. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FortiSIEM.Events.EventType | Unknown | FortiSIEM event type. |
| FortiSIEM.Events.SourceCountry | Unknown | Event source country. |
Command Example
!fortisiem-get-events-by-filter maxResults=4 srcIpAddr=10.100.100.17
Context Example
{
"FortiSIEM.Events": [
{
"Destination Host Name": "google-public-dns-a.google.com",
"Event Name": "Permitted traffic flow started",
"Destination IP": "8.8.8.8",
"Incident ID": "1919",
"Source IP": "10.100.100.17",
"Raw Event Log": "<14>May 2 19:53:33 PA-Firewall 1,2019/05/02 19:53:33,007151000004733,TRAFFIC,start,2304,2019/05/02 19:53:33,10.100.100.17,8.8.8.8,80.80.80.146,8.8.8.8,Internet allow,,,dns,vsys1,Trust,Untrust,ethernet1/3,ethernet1/1,Forward to Fortisiem,2019/05/02 19:53:33,156575,1,57184,53,59686,53,0x400000,udp,allow,109,109,0,1,2019/05/02 19:53:31,0,any,0,32724731,0x0,10.0.0.0-10.255.255.255,United States,0,1,0,n/a,0,0,0,0,,PA-Firewall,from-policy,,,0,,0,,N/A,0,0,0,0,dcc8adba-6c1a-4eb1-9ac3-d0f33439ea67,0",
"Reporting IP": "10.100.100.254",
"Source TCP/UDP Port": "57184",
"IP Protocol": "17 (UDP)",
"ExtendedData": {
"1121": "HOST-10.100.100.17",
"1126": "Trust",
"1127": "Untrust",
"3061": "dns",
"3001": "",
"110": 10000,
"3008": "dns",
"24": "LOW",
"20": "Permitted traffic flow started",
"21": 1,
"1": "PAN-OS-TRAFFIC-start-allow",
"1038": 0,
"5": "0 (Permit)",
"8": "10.10.10.254",
"1010": "17 (UDP)",
"2422": "Google",
"1151": "allow",
"1150": "Internet allow",
"9": "10.10.10.254",
"2410": "United States",
"1004": "8.8.8.8",
"1002": "google-public-dns-a.google.com",
"1001": "8.8.8.8",
"1000": "10.10.10.17"
...
},
"Event Receive Time": 1556690013000,
"Event Type": "PAN-OS-TRAFFIC-start-allow",
"Destination TCP/UDP Port": "53 (DOMAIN)",
"Event ID": "8255801804490150940"
},
...
]
}
Human Readable Output
| Event Receive Time | Event Type | Event Name | Source IP | Destination IP | Destination Host Name | IP Protocol | Source TCP/UDP Port | Destination TCP/UDP Port | Reporting IP | Raw Event Log |
|---|---|---|---|---|---|---|---|---|---|---|
| 1556690013000 | PAN-OS-TRAFFIC-start-allow | Permitted traffic flow started | 10.10.10.17 | 8.8.8.8 | google-public-dns-a.google.com | 17 (UDP) | 57184 | 53 (DOMAIN) | 10.10.10.254 | <14>May 2 19:53:33 PA-Firewall 1,2019/05/02 19:53:33,007151000004733,TRAFFIC,start,2304,2019/05/01 09:53:33,10.100.100.17,8.8.8.8,80.227.43.146,8.8.8.8,Internet allow,dns,vsys1,Trust,Untrust,ethernet1/3,ethernet1/1,Forward to Fortisiem,2019/05/02 19:53:33,156575,1,57184,53,59686,53,0x400000,udp,allow,109,109,0,1,2019/05/02 19:53:31,0,any,0,32724731,0x0,10.0.0.0-10.255.255.255,United States,0,1,0,n/a,0,0,0,0,PA-Firewall,from-policy,0,0,N/A,0,0,0,0,dcc8adba-6c1a-4eb1-9ac3-d0f33439ea67,0 |
4. Get device descriptions
Returns the description of each device.
Base Command
fortisiem-get-cmdb-devices
Input
| Argument Name | Description | Required |
|---|---|---|
| device_ip | CSV list of device IPs. | Optional |
| limit | Maximum number of results to return. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FortiSIEM.CmdbDevice | Unknown | CMDB devices. |
Command Example
!fortisiem-get-cmdb-devices limit=4
Context Example
{
"FortiSIEM.CmdbDevices": [
{
"Name": "HOST-10.10.10.230",
"DiscoverTime": "N/A",
"WinMachineGuid": "N/A",
"CreationMethod": "N/A",
"UpdateMethod": "N/A",
"Version": "N/A",
"DeviceType": "FortiSIEM Fortinet",
"Unmanaged": "false",
"AccessIp": "10.10.10.230",
"DiscoverMethod": "N/A",
"Approved": "false"
},
{
"Name": "HOST-10.10.10.21",
"DiscoverTime": "N/A",
"WinMachineGuid": "N/A",
"CreationMethod": "N/A",
"UpdateMethod": "N/A",
"Version": "N/A",
"DeviceType": "FortiSIEM Fortinet",
"Unmanaged": "false",
"AccessIp": "10.10.10.21",
"DiscoverMethod": "N/A",
"Approved": "false"
},
{
"Name": "HOST-10.10.10.243",
"DiscoverTime": "N/A",
"WinMachineGuid": "N/A",
"CreationMethod": "N/A",
"UpdateMethod": "N/A",
"Version": "N/A",
"DeviceType": "FortiSIEM Fortinet",
"Unmanaged": "false",
"AccessIp": "10.10.10.243",
"DiscoverMethod": "N/A",
"Approved": "false"
},
{
"Name": "HOST-10.10.10.241",
"DiscoverTime": "N/A",
"WinMachineGuid": "N/A",
"CreationMethod": "N/A",
"UpdateMethod": "N/A",
"Version": "N/A",
"DeviceType": "FortiSIEM Fortinet",
"Unmanaged": "false",
"AccessIp": "10.10.10.241",
"DiscoverMethod": "N/A",
"Approved": "false"
}
]
}
Human Readable Output
Devices
| Name | DiscoverTime | Version | DeviceType | AccessIp | WinMachineGuid | CreationMethod | UpdateMethod | Unmanaged | DiscoverMethod | Approved |
|---|---|---|---|---|---|---|---|---|---|---|
| HOST-10.10.10.230 | N/A | N/A | FortiSIEM Fortinet | 10.10.10.230 | N/A | N/A | N/A | false | N/A | false |
| HOST-10.10.10.21 | N/A | N/A | FortiSIEM Fortinet | 10.10.10.21 | N/A | N/A | N/A | false | N/A | false |
| HOST-10.10.10.243 | N/A | N/A | FortiSIEM Fortinet | 10.10.10.243 | N/A | N/A | N/A | false | N/A | false |
| HOST-10.10.10.241 | N/A | N/A | FortiSIEM Fortinet | 10.10.10.241 | N/A | N/A | N/A | false | N/A | false |
5. Get events using a query
Returns an event list filtered by a query.
Base Command
fortisiem-get-events-by-query
Input
| Argument Name | Description | Required |
|---|---|---|
| query | The query to get events. | Required |
| report-window | Interval time of the search. | Optional |
| interval-type | Interval unit. | Optional |
| limit | Maximum number of results to return. | Optional |
| extended-data | Whether to extend the data. | Optional |
| max-wait-time | Command timeout. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FortiSIEM.Events.EventType | Unknown | FortiSIEM event type. |
| FortiSIEM.Events.SourceCountry | Unknown | Event source country. |
Command Example
!fortisiem-get-events-by-query query=`destIpAddr = 116.202.56.112 OR destIpAddr = 17.252.141.15` interval-type=Hourly report-window=17
Context Example
{
"FortiSIEM.Events": [
{
"Event Name": "Permitted traffic flow started",
"Destination IP": "116.202.56.112",
"Incident ID": null,
"Raw Event Log": "<14>Apr 30 17:42:25 PA-Firewall 1,2019/04/30 17:42:24,007151000004733,TRAFFIC,start,2304,2019/04/30 17:42:24,10.100.100.66,116.202.56.112,80.227.43.146,116.202.56.112,Internet allow,,,ssl,vsys1,Trust,Untrust,ethernet1/3,ethernet1/1,Forward to Fortisiem,2019/04/30 17:42:24,201358,1,54273,443,51021,443,0x400000,tcp,allow,553,487,66,4,2019/04/30 17:42:22,0,any,0,32241586,0x0,10.0.0.0-10.255.255.255,Germany,0,3,1,n/a,0,0,0,0,,PA-Firewall,from-policy,,,0,,0,,N/A,0,0,0,0,dcc8adba-6c1a-4eb1-9ac3-d0f33439ea67,0",
"Reporting IP": "10.100.100.254",
"ExtendedData": {
"1322": 4,
"4188": "Syslog",
"1121": "HOST-10.100.100.66",
"2430": "77.2167",
"1126": "Trust",
"1127": "Untrust",
"3061": "ssl",
"3001": "",
"110": 10000,
"3008": "ssl",
"2531": "Emirates Integrated Telecommunications Company PJS",
"24": "LOW",
"20": "Permitted traffic flow started",
"21": 1,
"44": "PAN-OS",
"2529": "Dubai",
"2528": "United Arab Emirates",
"1": "PAN-OS-TRAFFIC-start-allow",
"1038": 0,
"2": 1,
"5": "0 (Permit)",
"7": 1556631745000,
"6": 1556631742000,
"1014": "443 (HTTPS)",
"8": "10.100.100.254",
"1010": "6 (TCP)",
"1011": 54273,
"1012": "443 (HTTPS)",
"1013": 51021,
"43": "Palo Alto",
"2422": "MTS",
"1151": "allow",
"1150": "Internet allow",
"2426": "28.6667",
"9": "10.100.100.254",
"122": "PaloAltoParser",
"17": 1,
"2533": "55.3081",
"128": 3,
"129": 1,
"11": "PA-Firewall",
"1284": 553,
"12": 1,
"15": "8255801804489112226",
"1046": "201358",
"1023": "ethernet1/1",
"1022": "ethernet1/3",
"3035": "any",
"16": "4 (Traffic)",
"53": "Super",
"2410": "India",
"3000": "",
"2414": "Delhi",
"1100": 1,
"2532": "25.2639",
"2418": "Delhi",
"2530": "Dubai",
"1004": "116.202.56.112",
"1003": "80.227.43.146",
"1002": "static.112.56.202.116.clients.your-server.de",
"1001": "116.202.56.112",
"1000": "10.100.100.66"
},
"Event Receive Time": 1556631745000,
"Event Type": "PAN-OS-TRAFFIC-start-allow",
"Event ID": "8255801804489112226"
},
{
"Event Name": "Permitted traffic flow started",
"Destination IP": "116.202.56.112",
"Incident ID": null,
"Raw Event Log": "<14>Apr 30 17:42:26 PA-Firewall 1,2019/04/30 17:42:25,007151000004733,TRAFFIC,start,2304,2019/04/30 17:42:25,10.100.100.66,116.202.56.112,80.227.43.146,116.202.56.112,Internet allow,,,ssl,vsys1,Trust,Untrust,ethernet1/3,ethernet1/1,Forward to Fortisiem,2019/04/30 17:42:25,195836,1,54274,443,1459,443,0x400000,tcp,allow,493,427,66,3,2019/04/30 17:42:24,0,any,0,32241609,0x0,10.0.0.0-10.255.255.255,Germany,0,2,1,n/a,0,0,0,0,,PA-Firewall,from-policy,,,0,,0,,N/A,0,0,0,0,dcc8adba-6c1a-4eb1-9ac3-d0f33439ea67,0",
"Reporting IP": "10.100.100.254",
"ExtendedData": {
"1322": 3,
"4188": "Syslog",
"1121": "HOST-10.100.100.66",
"2430": "77.2167",
"1126": "Trust",
"1127": "Untrust",
"3061": "ssl",
"3001": "",
"110": 10000,
"3008": "ssl",
"2531": "Emirates Integrated Telecommunications Company PJS",
"24": "LOW",
"20": "Permitted traffic flow started",
"21": 1,
"44": "PAN-OS",
"2529": "Dubai",
"2528": "United Arab Emirates",
"1": "PAN-OS-TRAFFIC-start-allow",
"1038": 0,
"2": 1,
"5": "0 (Permit)",
"7": 1556631746000,
"6": 1556631744000,
"1014": "443 (HTTPS)",
"8": "10.100.100.254",
"1010": "6 (TCP)",
"1011": 54274,
"1012": "443 (HTTPS)",
"1013": 1459,
"43": "Palo Alto",
"2422": "MTS",
"1151": "allow",
"1150": "Internet allow",
"2426": "28.6667",
"9": "10.100.100.254",
"122": "PaloAltoParser",
"17": 1,
"2533": "55.3081",
"128": 2,
"129": 1,
"11": "PA-Firewall",
"1284": 493,
"12": 1,
"15": "8255801804489112236",
"1046": "195836",
"1023": "ethernet1/1",
"1022": "ethernet1/3",
"3035": "any",
"16": "4 (Traffic)",
"53": "Super",
"2410": "India",
"3000": "",
"2414": "Delhi",
"1100": 1,
"2532": "25.2639",
"2418": "Delhi",
"2530": "Dubai",
"1004": "116.202.56.112",
"1003": "80.227.43.146",
"1002": "static.112.56.202.116.clients.your-server.de",
"1001": "116.202.56.112",
"1000": "10.100.100.66"
},
"Event Receive Time": 1556631746000,
"Event Type": "PAN-OS-TRAFFIC-start-allow",
"Event ID": "8255801804489112236"
},
{
"Event Name": "Permitted traffic flow started",
"Destination IP": "116.202.56.112",
"Incident ID": null,
"Raw Event Log": "<14>Apr 30 17:42:27 PA-Firewall 1,2019/04/30 17:42:26,007151000004733,TRAFFIC,start,2304,2019/04/30 17:42:26,10.100.100.66,116.202.56.112,80.227.43.146,116.202.56.112,Internet allow,,,ssl,vsys1,Trust,Untrust,ethernet1/3,ethernet1/1,Forward to Fortisiem,2019/04/30 17:42:26,200640,1,59920,443,27164,443,0x400000,tcp,allow,775,709,66,4,2019/04/30 17:42:24,0,any,0,32241625,0x0,10.0.0.0-10.255.255.255,Germany,0,3,1,n/a,0,0,0,0,,PA-Firewall,from-policy,,,0,,0,,N/A,0,0,0,0,dcc8adba-6c1a-4eb1-9ac3-d0f33439ea67,0",
"Reporting IP": "10.100.100.254",
"ExtendedData": {
"1322": 4,
"4188": "Syslog",
"1121": "HOST-10.100.100.66",
"2430": "77.2167",
"1126": "Trust",
"1127": "Untrust",
"3061": "ssl",
"3001": "",
"110": 10000,
"3008": "ssl",
"2531": "Emirates Integrated Telecommunications Company PJS",
"24": "LOW",
"20": "Permitted traffic flow started",
"21": 1,
"44": "PAN-OS",
"2529": "Dubai",
"2528": "United Arab Emirates",
"1": "PAN-OS-TRAFFIC-start-allow",
"1038": 0,
"2": 1,
"5": "0 (Permit)",
"7": 1556631747000,
"6": 1556631744000,
"1014": "443 (HTTPS)",
"8": "10.100.100.254",
"1010": "6 (TCP)",
"1011": 59920,
"1012": "443 (HTTPS)",
"1013": 27164,
"43": "Palo Alto",
"2422": "MTS",
"1151": "allow",
"1150": "Internet allow",
"2426": "28.6667",
"9": "10.100.100.254",
"122": "PaloAltoParser",
"17": 1,
"2533": "55.3081",
"128": 3,
"129": 1,
"11": "PA-Firewall",
"1284": 775,
"12": 1,
"15": "8255801804489310488",
"1046": "200640",
"1023": "ethernet1/1",
"1022": "ethernet1/3",
"3035": "any",
"16": "4 (Traffic)",
"53": "Super",
"2410": "India",
"3000": "",
"2414": "Delhi",
"1100": 1,
"2532": "25.2639",
"2418": "Delhi",
"2530": "Dubai",
"1004": "116.202.56.112",
"1003": "80.227.43.146",
"1002": "static.112.56.202.116.clients.your-server.de",
"1001": "116.202.56.112",
"1000": "10.100.100.66"
},
"Event Receive Time": 1556631747000,
"Event Type": "PAN-OS-TRAFFIC-start-allow",
"Event ID": "8255801804489310488"
}
]
}
Human Readable Output
FortiSIEM Event Results
| Event Receive Time | Reporting IP | Event Type | Event Name | Raw Event Log | Destination IP |
|---|---|---|---|---|---|
| 1556631745000 | 10.100.100.254 | PAN-OS-TRAFFIC-start-allow | Permitted traffic flow started | <14>Apr 30 17:42:25 PA-Firewall 1,2019/04/30 17:42:24,007151000004733,TRAFFIC,start,2304,2019/04/30 17:42:24,10.100.100.66,116.202.56.112,80.227.43.146,116.202.56.112,Internet allow,ssl,vsys1,Trust,Untrust,ethernet1/3,ethernet1/1,Forward to Fortisiem,2019/04/30 17:42:24,201358,1,54273,443,51021,443,0x400000,tcp,allow,553,487,66,4,2019/04/30 17:42:22,0,any,0,32241586,0x0,10.0.0.0-10.255.255.255,Germany,0,3,1,n/a,0,0,0,0,PA-Firewall,from-policy,0,0,N/A,0,0,0,0,dcc8adba-6c1a-4eb1-9ac3-d0f33439ea67,0 | 116.202.56.112 |
| 1556631746000 | 10.100.100.254 | PAN-OS-TRAFFIC-start-allow | Permitted traffic flow started | <14>Apr 30 17:42:26 PA-Firewall 1,2019/04/30 17:42:25,007151000004733,TRAFFIC,start,2304,2019/04/30 17:42:25,10.100.100.66,116.202.56.112,80.227.43.146,116.202.56.112,Internet allow,ssl,vsys1,Trust,Untrust,ethernet1/3,ethernet1/1,Forward to Fortisiem,2019/04/30 17:42:25,195836,1,54274,443,1459,443,0x400000,tcp,allow,493,427,66,3,2019/04/30 17:42:24,0,any,0,32241609,0x0,10.0.0.0-10.255.255.255,Germany,0,2,1,n/a,0,0,0,0,PA-Firewall,from-policy,0,0,N/A,0,0,0,0,dcc8adba-6c1a-4eb1-9ac3-d0f33439ea67,0 | 116.202.56.112 |
| 1556631747000 | 10.100.100.254 | PAN-OS-TRAFFIC-start-allow | Permitted traffic flow started | <14>Apr 30 17:42:27 PA-Firewall 1,2019/04/30 17:42:26,007151000004733,TRAFFIC,start,2304,2019/04/30 17:42:26,10.100.100.66,116.202.56.112,80.227.43.146,116.202.56.112,Internet allow,ssl,vsys1,Trust,Untrust,ethernet1/3,ethernet1/1,Forward to Fortisiem,2019/04/30 17:42:26,200640,1,59920,443,27164,443,0x400000,tcp,allow,775,709,66,4,2019/04/30 17:42:24,0,any,0,32241625,0x0,10.0.0.0-10.255.255.255,Germany,0,3,1,n/a,0,0,0,0,PA-Firewall,from-policy,0,0,N/A,0,0,0,0,dcc8adba-6c1a-4eb1-9ac3-d0f33439ea67,0 | 116.202.56.112 |
6. Get all resource lists
Get all FortiSIEM resource lists hierarchy.
Base Command
fortisiem-get-lists
Input
There are no input arguments for this command.
Context Output
There is no context output for this command.
Command Example
!fortisiem-get-lists
Context Example
{
"FortiSIEM.ResourceList": [
{
"ResourceType": "Reports",
"NatualID": "PH_SYS_REPORT_Freq",
"DisplayName": "Frequently Used",
"Children": [],
"ID": 500425
},
{
"ResourceType": "Reports",
"NatualID": "PH_SYS_REPORT_Incident",
"DisplayName": "Incidents",
"Children": [],
"ID": 500427
},
{
"ResourceType": "Malware IP",
"NatualID": "Emerging_Threat_Malware_IP_testing_1",
"DisplayName": "testing",
"Children": [
"l4"
],
"ID": 766037000
},
{
"ResourceType": "Malware IP",
"NatualID": "testing_l4_1",
"DisplayName": "l4",
"Children": [],
"ID": 766037001
},
{
"ResourceType": "User Agent",
"NatualID": "PH_SYS_HTTP_UA_BLACKLIST",
"DisplayName": "User Agent Blacklist",
"Children": [],
"ID": 500675
},
{
"ResourceType": "User Agent",
"NatualID": "PH_SYS_HTTP_UA_WHITELIST",
"DisplayName": "User Agent Whitelist",
"Children": [],
"ID": 500676
},
{
"ResourceType": "User Agent",
"NatualID": "User_Agents_Ungrouped_1",
"DisplayName": "Ungrouped",
"Children": [],
"ID": -1
}
]
}
Human Readable Output
Lists:
| ResourceType | NatualID | DisplayName | ID | Children |
|---|---|---|---|---|
| Reports | PH_SYS_REPORT_Freq | Frequently Used | 500425 | |
| Reports | PH_SYS_REPORT_Incident | Incidents | 500427 | |
| Malware IP | Emerging_Threat_Malware_IP_testing_1 | testing | 766037000 | l4 |
| Malware IP | testing_l4_1 | l4 | 766037001 | |
| User Agent | PH_SYS_HTTP_UA_BLACKLIST | User Agent Blacklist | 500675 | |
| User Agent | PH_SYS_HTTP_UA_WHITELIST | User Agent Whitelist | 500676 | |
| User Agent | User_Agents_Ungrouped_1 | Ungrouped | -1 |
7. Add an element to a resource list.
Adds an element to a resource list.
Base Command
fortisiem-add-item-to-resource-list
Input
| Argument Name | Description | Required |
|---|---|---|
| group_id | ID of the resource group. Run the fortisiem-get-lists command to get the ID. command. | Required |
| object-info | CSV list of key-value pairs of attributes, for example: name=SomeName,lowIp=192.168.1.1,highIp=192.168.1.2 | Required |
| resource_type | Resource type. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| FortiSIEM.Resource | Unknown | Resource object in FortiSIEM lists. |
Command Example
!fortisiem-add-item-to-resource-list resource_type="Malware Domains" group_id=766567954 object-info=domainName=test.domain.com,ipAddr=2.2.2.2,org=TeST
Context Example
{
"FortiSIEM.Resource": {
"xmlId": "MalwareSite$test.domain.com",
"domainName": "test.domain.com",
"ipAddr": "2.2.2.2",
"creationTime": 1556692917786,
"naturalId": "test.domain.com",
"systemEntity": true,
"id": 936390355,
"sysDefined": false,
"lastModifiedDate": 1556692917786,
"lastModified": 1556692917786,
"active": true,
"org": "TeST",
"creationDate": 1556692917786,
"custId": 0,
"groupId": 766567954,
"naturalIdProperty": "naturalId",
"ownerId": 500151
}
}
Human Readable Output
Resource was added:
| naturalId | systemEntity | id | groupId | sysDefined | custId | naturalIdProperty | xmlId | lastModifiedDate | ipAddr | active | org | creationDate | domainName | lastModified | creationTime | ownerId |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| test.domain.com | true | 936390355 | 766567954 | false | 0 | naturalId | MalwareSite$test.domain.com | 1556692917786 | 2.2.2.2 | true | TeST | 1556692917786 | test.domain.com | 1556692917786 | 1556692917786 | 500151 |
8. Remove elements from a resource list
Removes elements from a resource list.
Base Command
fortisiem-remove-item-from-resource-list
Input
| Argument Name | Description | Required |
|---|---|---|
| ids | CSV list of resource IDs. | Required |
| resource_type | Resource type. | Required |
Context Output
There is no context output for this command.
Command Example
!fortisiem-remove-item-from-resource-list resource_type="Malware Domains" ids=936390353
Human Readable Output
items with id [u’936390353’] were removed.
9. Get a list of all elements in a resource list
Lists all elements in a resource list.
Base Command
fortisiem-get-resource-list
Input
| Argument Name | Description | Required |
|---|---|---|
| group_id | ID of the resource group. Run the fortisiem-get-lists command to get the ID. | Required |
| resource_type | Resource type. | Required |
Context Output
There is no context output for this command.
Command Example
!fortisiem-get-resource-list resource_type="Malware Domains" group_id=766567954
Context Example
{
"FortiSIEM.Resource": [
{
"origin": "User",
"domainName": "malware.com",
"ipAddr": "3.2.3.2",
"active": true,
"org": "TeST",
"id": 936390354
},
{
"origin": "User",
"domainName": "testing.com",
"ipAddr": "1.2.3.4",
"active": true,
"org": "TeST",
"id": 930309355
}
]
}
Human Readable Output
Resource list:
| Origin | Domain Name | Ip Addr | Id | Active | Org |
|---|---|---|---|---|---|
| User | malware.com | 3.2.3.2 | 936390354 | true | TeST |
| User | testing.com | 1.2.3.4 | 930309355 | true | TeST |
Configuration parameters
isFetch— Fetch incidentsincidentType— Incident typeincidentFetchInterval— Incidents Fetch Intervalhost— Server URL (e.g. https://192.168.0.1) (required)credentials— Credentials (required)unsecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (9)
-
fortisiem-add-item-to-resource-listadd element to a resource list.
-
fortisiem-clear-incidentClear (close) a FortiSIEM incident.
-
fortisiem-get-cmdb-devicesReturns the description of each device.
-
fortisiem-get-events-by-filterReturns an event list according to the specified filters.
-
fortisiem-get-events-by-incidentGet events by incidents.
-
fortisiem-get-events-by-queryReturns event list filtered by query.
-
fortisiem-get-listsGet all FortiSIEM resource lists hierarchy.
-
fortisiem-get-resource-listLists all elements in a resource list.
-
fortisiem-remove-item-from-resource-listRemoves elements from a resource list.
import json import re import time from xml.dom.minidom import Document, Node, parseString import demistomock as demisto import requests import urllib3 from CommonServerPython import * from CommonServerUserPython import * # disable insecure warnings urllib3.disable_warnings() USERNAME = demisto.params()["credentials"]["identifier"] PASSWORD = demisto.params()["credentials"]["password"] AUTH = ("super/" + USERNAME, PASSWORD) VERIFY_SSL = not demisto.params().get("unsecure", False) HOST = demisto.params()["host"] QUERY_URL = HOST + "/phoenix/rest/query/" REST_ADDRESS = HOST + "/phoenix/rest/h5" EXTENDED_KEYS = {} # type: dict def load_extended_keys(): global EXTENDED_KEYS if demisto.command() == "fetch-incidents": last_run = demisto.getLastRun() EXTENDED_KEYS = last_run.get("extended_keys", {}) else: integration_context = demisto.getIntegrationContext() EXTENDED_KEYS = integration_context.get("extended_keys", {}) if not EXTENDED_KEYS: session = login() url = REST_ADDRESS + "/eventAttributeType/all" response = session.get(url, verify=VERIFY_SSL, auth=AUTH) EXTENDED_KEYS = {attr["attributeId"]: attr["displayName"] for attr in response.json()} if demisto.command() != "fetch-incidents": demisto.setIntegrationContext({"extended_keys": EXTENDED_KEYS}) def parse_resource_type(resource_type): type_to_url_path = { "Reports": "report", "Rules": "rule", "Networks": "resource/network", "Watch Lists": "rule/wl", "Protocols": "resource/port", "Event Type": "eventType", "Malware IP": "mal/ip", "Malware Domains": "mal/site", "Malware Urls": "mal/url", "Malware Hash": "mal/hash", "Malware Processes": "mal/proc", "Country Groups": "resource/geo", "Default Password": "mal/pwd", "Anonymity Network": "mal/proxy", "User Agents": "mal/agent", "Remediations": "remediation", } return type_to_url_path.get(resource_type, resource_type) @logger def validateSuccessfulResponse(resp, error_text): if resp.status_code != 200: return_error(f"Got response status {resp.status_code} when {error_text}") @logger def login(): session = requests.session() login_url = HOST + "/phoenix/login-html.jsf" response = session.get(login_url, verify=VERIFY_SSL) # get the VIEW_STATE from the xml returned in the UI login page. p = re.compile('(value=".{1046}==")') viewState = p.findall(response.text.encode("utf-8")) # type: ignore[arg-type, call-overload] VIEW_STATE = viewState[0][len('value="') :][:-1] data = { "loginHtml": "loginHtml", "loginHtml:username": USERNAME, "loginHtml:password": PASSWORD, "loginHtml:userDomain": "Empty", "loginHtml:loginBtn": "Log In", "loginHtml:domain": "super", "javax.faces.ViewState": VIEW_STATE, } headers = { "Upgrade-Insecure-Requests": "1", "Content-Type": "application/x-www-form-urlencoded", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8," "application/signed-exchange;v=b3;q=0.9", "Accept-Language": "en-US,en;q=0.9,pt-PT;q=0.8,pt;q=0.7", } response = session.post(login_url, headers=headers, data=data, verify=VERIFY_SSL) # type: ignore return session def clear_incident_command(): args = demisto.args() incident_id = args["incident_id"] reason = args.get("close_reason", "") raw_response = clear_incident(incident_id, reason) return_outputs("Incident cleared successfully.", {}, raw_response) @logger def clear_incident(incident_id, reason): session = login() headers = {"Accept": "application/json, text/plain, */*", "Content-Type": "application/json"} response = session.put( HOST + "/phoenix/rest/h5/incident/clear", params={"ids": [incident_id], "user": USERNAME}, headers=headers, data=reason, verify=VERIFY_SSL, ) validateSuccessfulResponse(response, "triggering events report") return response.text @logger def getEventsByIncident(incident_id, max_results, extended_data, max_wait_time): session = login() # response = session.get(HOST + '/phoenix/rest/h5/report/triggerEvent?rawMsg=' + incident_id) # validateSuccessfulResponse(response, "triggering events report") # # try: # jsonRes = response.json() # queryData = jsonRes[0]['right'] # except (ValueError, KeyError): # return_error("Got wrong response format when triggering events report. " # "Expected a json array but got:\n" + response.text) queryData = { "isReportService": True, "selectClause": "eventSeverityCat,incidentLastSeen,eventName,incidentRptDevName,incidentSrc,incidentTarget," "incidentDetail,incidentStatus,incidentReso,incidentId,eventType,incidentTicketStatus," "bizService,count,incidentClearedTime,incidentTicketUser,incidentNotiRecipients," "incidentClearedReason,incidentComments,eventSeverity,incidentFirstSeen,incidentRptIp," "incidentTicketId,customer,incidentNotiStatus,incidentClearedUser,incidentExtUser," "incidentExtClearedTime,incidentExtResoTime,incidentExtTicketId,incidentExtTicketState," "incidentExtTicketType,incidentViewStatus,rawEventMsg,phIncidentCategory,phSubIncidentCategory," "incidentRptDevStatus", "eventFilters": [ {"name": "Filter_OVERALL_STATUS", "singleConstraint": f"(phEventCategory = 1) AND incidentId = {incident_id}"} ], "hints": "IgnoreTime", } return getEventsByQuery( session, queryData, max_results, extended_data, max_wait_time, "FortiSIEM events for Incident " + incident_id, incident_id=incident_id, ) @logger def getEventsByQuery(session, queryData, max_results, extended_data, max_wait_time, tableTitle, incident_id=None): headers = {"Accept": "application/json, text/plain, */*", "Content-Type": "application/json"} response = session.post(REST_ADDRESS + "/report/run", headers=headers, data=json.dumps(queryData), verify=VERIFY_SSL) validateSuccessfulResponse(response, "running report") data = response.json() data["report"] = queryData data = json.dumps(data) # poll until report progress reaches 100 response = session.post(REST_ADDRESS + "/report/reportProgress", headers=headers, data=data, verify=VERIFY_SSL) # response contain the percentage of the report loading while response.text != "100" and max_wait_time > 0: response = session.post(REST_ADDRESS + "/report/reportProgress", headers=headers, data=data, verify=VERIFY_SSL) max_wait_time = int(max_wait_time) - 1 time.sleep(1) params = { "start": 0, "perPage": max_results, "allData": extended_data, } response = session.post(REST_ADDRESS + "/report/resultByReport", params=params, headers=headers, data=data, verify=VERIFY_SSL) try: res = response.json() eventKeys = res["headerData"]["columnNames"] except (ValueError, KeyError): return_error("Got wrong response format when getting report results. Expected a json object but got:\n" + response.text) # reformat results eventData = [] md = "" for key in res["lightValueObjects"]: cur = { "Event ID": key.get("naturalId", ""), "Incident ID": incident_id, } for i in range(len(eventKeys)): if len(key["data"]) == 0 or key["data"][0] == "No report results found.": md = "No report results found." break else: # noqa: RET508 cur[eventKeys[i]] = key["data"][i] if md != "": # no results were found, not need to loop break cur["ExtendedData"] = {} for extItem in key["extData"]: if EXTENDED_KEYS.get(extItem["left"]) is not None: cur[EXTENDED_KEYS.get(extItem["left"]).replace(" ", "")] = extItem["right"] # type: ignore else: cur["ExtendedData"][extItem["left"]] = extItem["right"] eventData.append(cur) md = tableToMarkdown(tableTitle, eventData, eventKeys) if md == "" else md demisto.results( { "ContentsFormat": formats["json"], "Type": entryTypes["note"], "Contents": res, "ReadableContentsFormat": formats["markdown"], "HumanReadable": md, "EntryContext": {'FortiSIEM.Events(val["Event ID"] && val["Event ID"] == obj["Event ID"])': eventData}, } ) @logger def GetEventQuery(): in_xml = create_query_xml("all", interval="1") url = QUERY_URL + "eventQuery" headers = {"Content-Type": "text/xml"} resp = requests.request("POST", url, headers=headers, data=in_xml, verify=VERIFY_SSL, auth=AUTH) validateSuccessfulResponse(resp, "fetching event query") queryId = resp.text if 'error code="255"' in queryId: return_error("Got error code 255 while getting event query. Make sure the query has valid syntax") return queryId @logger def GetIncidentsByOrg(queryId): # The request will poll until the server completes the query. url = QUERY_URL + "progress/" + queryId resp = requests.request("GET", url, verify=VERIFY_SSL, auth=AUTH) while resp.text != "100": resp = requests.request("GET", url, verify=VERIFY_SSL, auth=AUTH) outXML = [] if resp.text == "100": url = QUERY_URL + "events/" + queryId + "/0/1000" resp = requests.request("GET", url, verify=VERIFY_SSL, auth=AUTH) content = resp.text if content != "": outXML.append(content) # this code is taken directly from their documentation. # get all results (last "page" has less than 1000 records) p = re.compile(r'totalCount="\d+"') mlist = p.findall(content) if mlist and mlist[0] != "": mm = mlist[0].replace('"', "") m = int(mm.split("=")[-1]) num = 0 if m > 1000: num = int(m / 1000) if m % 1000 > 0: num += 1 if num > 0: for i in range(num): url = QUERY_URL + "events/" + queryId + "/" + str(i * 1000 + 1) + "/1000" resp = requests.request("GET", url, verify=VERIFY_SSL, auth=AUTH) content = resp.text if content != "": outXML.append(content) else: sys.exit(0) phCustId = "all" param = dumpXML(outXML, phCustId) return param @logger def create_query_xml( include_value, interval="", single_evt_value="phEventCategory=1", interval_type="Minute", attr_list=None, limit="All" ): doc = Document() reports = doc.createElement("Reports") doc.appendChild(reports) report = doc.createElement("Report") report.setAttribute("id", "") report.setAttribute("group", "report") reports.appendChild(report) name = doc.createElement("Name") report.appendChild(name) doc.createTextNode("All Incidents") custScope = doc.createElement("CustomerScope") custScope.setAttribute("groupByEachCustomer", "true") report.appendChild(custScope) include = doc.createElement("Include") if include_value == "all": include.setAttribute("all", "true") custScope.appendChild(include) else: custScope.appendChild(include) include_text = doc.createTextNode(include_value) include.appendChild(include_text) exclude = doc.createElement("Exclude") custScope.appendChild(exclude) description = doc.createElement("description") report.appendChild(description) select = doc.createElement("SelectClause") select.setAttribute("numEntries", limit) report.appendChild(select) attrList = doc.createElement("AttrList") if attr_list: attr_text = doc.createTextNode(str(attr_list)) attrList.appendChild(attr_text) select.appendChild(attrList) reportInterval = doc.createElement("ReportInterval") report.appendChild(reportInterval) window = doc.createElement("Window") window.setAttribute("unit", interval_type) window.setAttribute("val", interval) reportInterval.appendChild(window) pattern = doc.createElement("PatternClause") pattern.setAttribute("window", "3600") report.appendChild(pattern) subPattern = doc.createElement("SubPattern") subPattern.setAttribute("displayName", "Events") subPattern.setAttribute("name", "Events") pattern.appendChild(subPattern) single = doc.createElement("SingleEvtConstr") subPattern.appendChild(single) single_text = doc.createTextNode(single_evt_value) single.appendChild(single_text) _filter = doc.createElement("RelevantFilterAttr") report.appendChild(_filter) return doc.toxml() @logger def dumpXML(xmlList, phCustId): param = [] for xml in xmlList: doc = parseString(xml.encode("utf-8")) for node in doc.getElementsByTagName("events"): for node1 in node.getElementsByTagName("event"): mapping = {} for node2 in node1.getElementsByTagName("attributes"): for node3 in node2.getElementsByTagName("attribute"): item_name = node3.getAttribute("name") for node4 in node3.childNodes: if node4.nodeType == Node.TEXT_NODE: mapping[item_name] = node4.data if phCustId == "all" or mapping["phCustId"] == phCustId: param.append(mapping) return param @logger def buildQueryString(args): res_list = [] for key in args: if "IpAddr" not in key: res_list.append(f'{key} = "{args[key]}"') else: res_list.append(f"{key} = {args[key]}") return " AND ".join(res_list) @logger def getEventsByFilter(maxResults, extendedData, maxWaitTime, reportWindow, reportWindowUnit): session = login() args = demisto.args() del args["maxResults"] del args["extendedData"] del args["maxWaitTime"] del args["reportWindow"] del args["reportWindowUnit"] query_string = buildQueryString(args) query_data = { "isReportService": True, "selectClause": "phRecvTime,reptDevIpAddr,eventType,eventName,rawEventMsg,destIpAddr", "reportWindow": int(reportWindow), "reportWindowUnit": reportWindowUnit, "timeRangeRelative": True, "eventFilters": [{"groupBy": "", "singleConstraint": query_string}], "custId": 1, } return getEventsByQuery(session, query_data, maxResults, extendedData, maxWaitTime, "FortiSIEM Event Results") def parse_cmdb_list(cmdb_device): device_dict = { "DiscoverMethod": cmdb_device.get("discoverMethod", "N/A"), "Approved": cmdb_device.get("approved", "false"), "CreationMethod": cmdb_device.get("creationMethod", "N/A"), "AccessIp": cmdb_device.get("accessIp", "N/A"), "Name": cmdb_device.get("name", "N/A"), "WinMachineGuid": cmdb_device.get("winMachineGuid", "N/A"), "Unmanaged": cmdb_device.get("unmanaged", "false"), "Version": cmdb_device.get("version", "N/A"), "UpdateMethod": cmdb_device.get("updateMethod", "N/A"), } timestamp = cmdb_device.get("discoverTime", None) if timestamp and timestamp.isdigit(): device_dict["DiscoverTime"] = timestamp_to_datestring(timestamp) elif timestamp: device_dict["DiscoverTime"] = timestamp else: device_dict["DiscoverTime"] = "N/A" device_type = cmdb_device.get("deviceType") if device_type: device_dict["DeviceType"] = "{} {}".format(device_type["model"], device_type["vendor"]) else: device_dict["DeviceType"] = "N/A" return device_dict def get_cmdb_devices_command(): args = demisto.args() device_ip = args.get("device_ip") limit = int(args.get("limit")) raw_response = get_cmdb_devices(device_ip, limit) list_of_devices = list(map(parse_cmdb_list, raw_response)) return_outputs(tableToMarkdown("Devices", list_of_devices), {"FortiSIEM.CmdbDevices": list_of_devices}, raw_response) @logger def get_cmdb_devices(device_ip=None, limit=100): cmdb_url = HOST + "/phoenix/rest/cmdbDeviceInfo/devices" if device_ip: cmdb_url += "?includeIps=" + device_ip response = requests.get(cmdb_url, verify=VERIFY_SSL, auth=AUTH) list_of_devices = json.loads(xml2json(response.text)) if "response" in list_of_devices: return_error(list_of_devices["response"]["error"]["description"]) elif "devices" in list_of_devices: list_of_devices = list_of_devices["devices"]["device"] elif "device" in list_of_devices: list_of_devices = [list_of_devices["device"]] return list_of_devices[:limit] @logger def get_events_by_query(query, report_window="60", interval_type="Minute", limit="20", extended_data="false", max_wait_time=60): session = login() query_data = { "isReportService": True, "selectClause": "phRecvTime,reptDevIpAddr,eventType,eventName,rawEventMsg,destIpAddr", "reportWindow": int(report_window), "reportWindowUnit": interval_type, "timeRangeRelative": True, "eventFilters": [{"groupBy": "", "singleConstraint": query}], "custId": 1, } return getEventsByQuery(session, query_data, limit, extended_data, max_wait_time, "FortiSIEM Event Results") def get_lists_command(): raw_resources = get_lists() resources = [] for r in flatten_resources(raw_resources): resources.append( { "DisplayName": r["displayName"], "NatualID": r["naturalId"], "ID": r["id"], "ResourceType": r["groupType"]["displayName"], "Children": [c["displayName"] for c in r["children"]], } ) return_outputs( tableToMarkdown("Lists:", resources, removeNull=True), {"FortiSIEM.ResourceList(val.ID && val.ID == obj.ID)": resources}, raw_response=raw_resources, ) @logger def get_lists(): session = login() url = REST_ADDRESS + "/group/resource" response = session.get(url, verify=VERIFY_SSL, auth=AUTH) return response.json() def flatten_resources(raw_resources): for r in raw_resources: yield r # possible stackoverflow yield from flatten_resources(r["children"]) def add_item_to_resource_list_command(): args = demisto.args() resource_type = parse_resource_type(args["resource_type"]) group_id = args["group_id"] object_info = args.get("object-info", []) object_info = dict(object_property.strip().split("=", 1) for object_property in object_info.split(",")) raw_response = add_item_to_resource_list(resource_type, group_id, object_info) outputs = {"FortiSIEM.Resource(val.id && val.id == obj.id)": createContext(raw_response, removeNull=True)} return_outputs(tableToMarkdown("Resource was added:", raw_response, removeNull=True), outputs, raw_response) @logger def add_item_to_resource_list(resource_type, group_id, object_info): session = login() url = f"{REST_ADDRESS}/{resource_type}/save" object_info["groupId"] = group_id object_info["active"] = True object_info["sysDefined"] = False response = session.post(url, data=json.dumps(object_info), verify=VERIFY_SSL, auth=AUTH) response = response.json() if response.get("code", 0) == -1: return_error(response["msg"]) return response def remove_item_from_resource_list_command(): args = demisto.args() resource_type = parse_resource_type(args["resource_type"]) deleted_ids = args.get("ids", "").split(",") raw_response = remove_item_from_resource_list(resource_type, deleted_ids) return_outputs(raw_response, {}, raw_response=raw_response) @logger def remove_item_from_resource_list(resource_type, deleted_ids): session = login() url = f"{REST_ADDRESS}/{resource_type}/del" response = session.delete(url, params={"ids": json.dumps(deleted_ids)}, verify=VERIFY_SSL, auth=AUTH) if response.text != '"OK"': return_error(response.text) return f"items with id {deleted_ids} were removed." def get_resource_list_command(): args = demisto.args() resource_type = parse_resource_type(args["resource_type"]) group_id = args["group_id"] raw_response = get_resource_list(resource_type, group_id) headers = raw_response.get("headerData", {}).get("keys", []) ec = [] for element in raw_response.get("lightValueObjects", []): e = dict(zip(headers, element.get("data", []))) e["id"] = element.get("objectId") ec.append(e) outputs = {"FortiSIEM.Resource(val.id && val.id == obj.id)": createContext(ec, removeNull=True)} return_outputs(tableToMarkdown("Resource list:", ec, headerTransform=pascalToSpace, removeNull=True), outputs, raw_response) @logger def get_resource_list(resource_type, group_id): session = login() url = f"{REST_ADDRESS}/{resource_type}/list" params = { "groupId": group_id, "start": 0, "size": 50, } response = session.get(url, params=params, verify=VERIFY_SSL, auth=AUTH) response = response.json() if response.get("code", 0) == -1: return_error(response["msg"]) return response def convert_keys_to_snake_case(d): d = {k.replace("-", "_"): v for k, v in d.items()} return d def test(): try: login() except Exception as e: if isinstance(e, requests.exceptions.SSLError): demisto.results("Not verified certificate") else: demisto.results(str(e)) demisto.results("ok") def fetch_incidents(): query_id = GetEventQuery() res = GetIncidentsByOrg(query_id) known_ids = demisto.getLastRun().get("ids", None) if known_ids is None or not known_ids: known_ids = [] incidents = [] for inc in res: if inc.get("incidentId") not in known_ids: incidents.append({"name": inc.get("eventName", "New FortiSIEM Event"), "rawJSON": json.dumps(inc)}) if len(known_ids) >= 1000: known_ids.pop(0) known_ids.append(inc.get("incidentId")) demisto.setLastRun({"ids": known_ids, "extended_keys": EXTENDED_KEYS}) demisto.incidents(incidents) sys.exit(0) def main(): try: handle_proxy() load_extended_keys() if demisto.command() == "test-module": test() elif demisto.command() == "fetch-incidents": fetch_incidents() elif demisto.command() == "fortisiem-get-events-by-incident": args = demisto.args() getEventsByIncident(args["incID"], args["maxResults"], args["extendedData"], args["maxWaitTime"]) elif demisto.command() == "fortisiem-clear-incident": clear_incident_command() elif demisto.command() == "fortisiem-get-events-by-filter": args = demisto.args() getEventsByFilter( args["maxResults"], args["extendedData"], args["maxWaitTime"], args["reportWindow"], args["reportWindowUnit"] ) elif demisto.command() == "fortisiem-get-events-by-query": args = convert_keys_to_snake_case(demisto.args()) get_events_by_query(**args) elif demisto.command() == "fortisiem-get-cmdb-devices": get_cmdb_devices_command() elif demisto.command() == "fortisiem-get-lists": get_lists_command() elif demisto.command() == "fortisiem-add-item-to-resource-list": add_item_to_resource_list_command() elif demisto.command() == "fortisiem-remove-item-from-resource-list": remove_item_from_resource_list_command() elif demisto.command() == "fortisiem-get-resource-list": get_resource_list_command() except Exception as e: if demisto.command() == "fetch-incidents": LOG(str(e)) LOG.print_log() raise else: return_error(str(e)) # python2 uses __builtin__ python3 uses builtins if __name__ == "__builtin__" or __name__ == "builtins": main()