Bastille Networks
RF monitoring for wireless intrusion detection and policy enforcement. Visit https://www.bastille.net for details.
Network Security · Bastille Networks
Details
| ID | Bastille Networks |
|---|---|
| Provider | Bastille Networks |
| Category | Network Security |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
RF monitoring for wireless intrusion detection and policy enforcement. Visit https://www.bastille.net for details.
This integration was integrated and tested with Bastille Networks product version 1.5.0.
Configure BastilleNetworks in Cortex
| Parameter | Description | Required |
|---|---|---|
| api_url | Server URL | False |
| api_key | API Key | True |
| site | Site | True |
| concentrator | Concentrator | True |
| map | Map | True |
| isFetch | Fetch incidents | False |
| incidentType | Incident type | False |
| tags | Tags | False |
| event_types | Event types | 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.
bastille-get-device-events
Command to fetch device detection events
Base Command
bastille-get-device-events
Input
| Argument Name | Description | Required |
|---|---|---|
| protocol | Filter by transmitter protocol name | Optional |
| since | Earliest time to return incidents from | Optional |
| until | Latest time to return incidents from | Optional |
| limit | Limit the number of fetched events | Optional |
| tags | List of tags to filter events by | Optional |
| event_id | Unique identifier of the zone detection event | Optional |
| transmitter_id | Device identifier to query the detections for | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Bastille.DeviceEvent.event_id | String | Unique identifier of the event |
| Bastille.DeviceEvent.event_type | String | Type of the event |
| Bastille.DeviceEvent.time_s | Date | Event detection timestamp |
| Bastille.DeviceEvent.tags | String | Tags attached to the zone event |
| Bastille.DeviceEvent.zone_name | String | Zone name where the incident took place |
| Bastille.DeviceEvent.area.site_id | String | Deployment site identifier |
| Bastille.DeviceEvent.area.concentrator_id | String | Deployment concentrator identifier |
| Bastille.DeviceEvent.area.map_id | String | Deployment map identifier |
| Bastille.DeviceEvent.emitter.protocol | String | Wireless protcol used by the detected transmitter |
| Bastille.DeviceEvent.emitter.transmitter_id | String | Wireless transmitter identifier |
| Bastille.DeviceEvent.emitter.vendor | String | Wireless transmitter vendor |
| Bastille.DeviceEvent.emitter.network.name | String | Name of the network the transmitter is connected to |
| Bastille.DeviceEvent.device_info.manufacturer | String | Manufacturer associated with device in the deployment |
| Bastille.DeviceEvent.device_info.user | String | User associated with device in the deployment |
| Bastille.DeviceEvent.device_info.model | String | Model associated with device in the deployment |
| Bastille.DeviceEvent.device_info.name | String | Name associated with device in the deployment |
| Bastille.DeviceEvent.first_seen.time | Number | Event first seen timestamp |
| Bastille.DeviceEvent.first_seen.position | Unknown | Event first seen coordinates |
| Bastille.DeviceEvent.last_seen.time | Number | Event last seen timestamp |
| Bastille.DeviceEvent.last_seen.position | Unknown | Event last seen coordinates |
Command Example
!bastille-get-device-events since=2020-05-01T13:00:00T until=2020-05-01T17:00:00T
Context Example
{
"Bastille": {
"DeviceEvent": [
{
"area": {
"concentrator_id": "c1",
"map_id": "m1",
"site_id": "s1"
},
"device_info": {
"manufacturer": "Apple",
"model": "iPhone 7",
"name": "Jane's iPhone 7",
"user": "Jane Doe"
},
"emitter": {
"network": {
"name": "Verizon"
},
"protocol": "LTE",
"transmitter_id": "vzw:1100:249:6f4d",
"vendor": "Unknown"
},
"event_id": "LTE_vzw:1100:249:6f4d_s1_c1_m1_1588338000",
"event_type": "device_event",
"first_seen": {
"position": [
34.61,
13.31
],
"time_s": "2020-05-01T13:00:00+00:00"
},
"last_seen": {
"position": [
32.31,
11.24
],
"time_s": "2020-05-01T13:00:00+00:00"
},
"tags": [],
"time_s": "2020-05-01T13:00:00+00:00"
},
{
"area": {
"concentrator_id": "c1",
"map_id": "m1",
"site_id": "s1"
},
"device_info": {
"manufacturer": "Apple",
"model": "iPhone 7",
"name": "Jane's iPhone 7",
"user": "Jane Doe"
},
"emitter": {
"network": {
"name": "Verizon"
},
"protocol": "LTE",
"transmitter_id": "vzw:1100:249:6f4d",
"vendor": "Unknown"
},
"event_id": "LTE_vzw:1100:249:6f4d_s1_c1_m1_1588338060",
"event_type": "device_event",
"first_seen": {
"position": [
34.61,
13.31
],
"time_s": "2020-05-01T13:01:00+00:00"
},
"last_seen": {
"position": [
32.31,
11.24
],
"time_s": "2020-05-01T13:01:00+00:00"
},
"tags": [],
"time_s": "2020-05-01T13:01:00+00:00"
},
{
"area": {
"concentrator_id": "c1",
"map_id": "m1",
"site_id": "s1"
},
"device_info": {
"manufacturer": "Apple",
"model": "iPhone 7",
"name": "Jane's iPhone 7",
"user": "Jane Doe"
},
"emitter": {
"network": {
"name": "Verizon"
},
"protocol": "LTE",
"transmitter_id": "vzw:1100:249:6f4d",
"vendor": "Unknown"
},
"event_id": "LTE_vzw:1100:249:6f4d_s1_c1_m1_1588338120",
"event_type": "device_event",
"first_seen": {
"position": [
34.61,
13.31
],
"time_s": "2020-05-01T13:02:00+00:00"
},
"last_seen": {
"position": [
32.31,
11.24
],
"time_s": "2020-05-01T13:02:00+00:00"
},
"tags": [],
"time_s": "2020-05-01T13:02:00+00:00"
},
{
"area": {
"concentrator_id": "c1",
"map_id": "m1",
"site_id": "s1"
},
"device_info": {
"manufacturer": "Apple",
"model": "iPhone 7",
"name": "Jane's iPhone 7",
"user": "Jane Doe"
},
"emitter": {
"network": {
"name": "Verizon"
},
"protocol": "LTE",
"transmitter_id": "vzw:1100:249:6f4d",
"vendor": "Unknown"
},
"event_id": "LTE_vzw:1100:249:6f4d_s1_c1_m1_1588338180",
"event_type": "device_event",
"first_seen": {
"position": [
34.61,
13.31
],
"time_s": "2020-05-01T13:03:00+00:00"
},
"last_seen": {
"position": [
32.31,
11.24
],
"time_s": "2020-05-01T13:03:00+00:00"
},
"tags": [],
"time_s": "2020-05-01T13:03:00+00:00"
},
{
"area": {
"concentrator_id": "c1",
"map_id": "m1",
"site_id": "s1"
},
"device_info": {
"manufacturer": "Apple",
"model": "iPhone 7",
"name": "Jane's iPhone 7",
"user": "Jane Doe"
},
"emitter": {
"network": {
"name": "Verizon"
},
"protocol": "LTE",
"transmitter_id": "vzw:1100:249:6f4d",
"vendor": "Unknown"
},
"event_id": "LTE_vzw:1100:249:6f4d_s1_c1_m1_1588338240",
"event_type": "device_event",
"first_seen": {
"position": [
34.61,
13.31
],
"time_s": "2020-05-01T13:04:00+00:00"
},
"last_seen": {
"position": [
32.31,
11.24
],
"time_s": "2020-05-01T13:04:00+00:00"
},
"tags": [],
"time_s": "2020-05-01T13:04:00+00:00"
}
]
}
}
Human Readable Output
Device Events
area device_info emitter event_id first_seen last_seen tags time_s site_id: s1
concentrator_id: c1
map_id: m1manufacturer: Apple
user: Jane Doe
model: iPhone 7
name: Jane’s iPhone 7protocol: LTE
transmitter_id: vzw:1100:249:6f4d
vendor: Unknown
network: {“name”: “Verizon”}LTE_vzw:1100:249:6f4d_s1_c1_m1_1588338000 time_s: 2020-05-01T13:00:00+00:00
position: 34.61,
13.31position: 32.31,
11.24
time_s: 2020-05-01T13:00:00+00:002020-05-01T13:00:00+00:00 site_id: s1
concentrator_id: c1
map_id: m1manufacturer: Apple
user: Jane Doe
model: iPhone 7
name: Jane’s iPhone 7protocol: LTE
transmitter_id: vzw:1100:249:6f4d
vendor: Unknown
network: {“name”: “Verizon”}LTE_vzw:1100:249:6f4d_s1_c1_m1_1588338060 time_s: 2020-05-01T13:01:00+00:00
position: 34.61,
13.31position: 32.31,
11.24
time_s: 2020-05-01T13:01:00+00:002020-05-01T13:01:00+00:00 site_id: s1
concentrator_id: c1
map_id: m1manufacturer: Apple
user: Jane Doe
model: iPhone 7
name: Jane’s iPhone 7protocol: LTE
transmitter_id: vzw:1100:249:6f4d
vendor: Unknown
network: {“name”: “Verizon”}LTE_vzw:1100:249:6f4d_s1_c1_m1_1588338120 time_s: 2020-05-01T13:02:00+00:00
position: 34.61,
13.31position: 32.31,
11.24
time_s: 2020-05-01T13:02:00+00:002020-05-01T13:02:00+00:00 site_id: s1
concentrator_id: c1
map_id: m1manufacturer: Apple
user: Jane Doe
model: iPhone 7
name: Jane’s iPhone 7protocol: LTE
transmitter_id: vzw:1100:249:6f4d
vendor: Unknown
network: {“name”: “Verizon”}LTE_vzw:1100:249:6f4d_s1_c1_m1_1588338180 time_s: 2020-05-01T13:03:00+00:00
position: 34.61,
13.31position: 32.31,
11.24
time_s: 2020-05-01T13:03:00+00:002020-05-01T13:03:00+00:00 site_id: s1
concentrator_id: c1
map_id: m1manufacturer: Apple
user: Jane Doe
model: iPhone 7
name: Jane’s iPhone 7protocol: LTE
transmitter_id: vzw:1100:249:6f4d
vendor: Unknown
network: {“name”: “Verizon”}LTE_vzw:1100:249:6f4d_s1_c1_m1_1588338240 time_s: 2020-05-01T13:04:00+00:00
position: 34.61,
13.31position: 32.31,
11.24
time_s: 2020-05-01T13:04:00+00:002020-05-01T13:04:00+00:00
bastille-get-zone-events
Command to fetch zone detection events
Base Command
bastille-get-zone-events
Input
| Argument Name | Description | Required |
|---|---|---|
| zone | Filter by zone name | Optional |
| protocol | Filter by transmitter protocol name | Optional |
| since | Earliest time to return incidents from | Optional |
| until | Latest time to return incidents from | Optional |
| limit | Limit the number of fetched events | Optional |
| tags | List of tags to filter events by | Optional |
| event_id | Unique identifier of the zone detection event | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Bastille.ZoneEvent.event_id | String | Unique identifier of the event |
| Bastille.ZoneEvent.event_type | String | Type of the event |
| Bastille.ZoneEvent.time_s | Date | Event detection timestamp |
| Bastille.ZoneEvent.tags | String | Tags attached to the zone event |
| Bastille.ZoneEvent.zone_name | String | Zone name where the incident took place |
| Bastille.ZoneEvent.area.site_id | String | Deployment site identifier |
| Bastille.ZoneEvent.area.concentrator_id | String | Deployment concentrator identifier |
| Bastille.ZoneEvent.area.map_id | String | Deployment map identifier |
| Bastille.ZoneEvent.emitter.protocol | String | Wireless protcol used by the detected transmitter |
| Bastille.ZoneEvent.emitter.transmitter_id | String | Wireless transmitter identifier |
| Bastille.ZoneEvent.emitter.vendor | String | Wireless transmitter vendor |
| Bastille.ZoneEvent.emitter.network.name | String | Name of the network the transmitter is connected to |
| Bastille.ZoneEvent.device_info.manufacturer | String | Manufacturer associated with device in the deployment |
| Bastille.ZoneEvent.device_info.user | String | User associated with device in the deployment |
| Bastille.ZoneEvent.device_info.model | String | Model associated with device in the deployment |
| Bastille.ZoneEvent.device_info.name | String | Name associated with device in the deployment |
| Bastille.ZoneEvent.first_seen.time | Number | Event first seen timestamp |
| Bastille.ZoneEvent.first_seen.position | Unknown | Event first seen coordinates |
| Bastille.ZoneEvent.last_seen.time | Number | Event last seen timestamp |
| Bastille.ZoneEvent.last_seen.position | Unknown | Event last seen coordinates |
Command Example
!bastille-get-zone-events zone=conference-1
Context Example
{
"Bastille": {
"ZoneEvent": [
{
"area": {
"concentrator_id": "c1",
"map_id": "m1",
"site_id": "s1"
},
"device_info": {
"manufacturer": "Apple",
"model": "iPhone 7",
"name": "Jane's iPhone 7",
"user": "Jane Doe"
},
"emitter": {
"network": {
"name": "Verizon"
},
"protocol": "LTE",
"transmitter_id": "vzw:1100:249:6f4d",
"vendor": "Unknown"
},
"event_id": "conference-1_LTE_vzw:1100:249:6f4d_s1_c1_m1_1585699200",
"event_type": "zone_event",
"first_seen": {
"position": [
34.61,
13.31
],
"time_s": "2020-04-01T00:00:00+00:00"
},
"last_seen": {
"position": [
32.31,
11.24
],
"time_s": "2020-04-01T00:00:00+00:00"
},
"tags": [],
"time_s": "2020-04-01T00:00:00+00:00",
"zone_name": "conference-1"
},
{
"area": {
"concentrator_id": "c1",
"map_id": "m1",
"site_id": "s1"
},
"device_info": {
"manufacturer": "Apple",
"model": "iPhone 7",
"name": "Jane's iPhone 7",
"user": "Jane Doe"
},
"emitter": {
"network": {
"name": "Verizon"
},
"protocol": "LTE",
"transmitter_id": "vzw:1100:249:6f4d",
"vendor": "Unknown"
},
"event_id": "conference-1_LTE_vzw:1100:249:6f4d_s1_c1_m1_1585699260",
"event_type": "zone_event",
"first_seen": {
"position": [
34.61,
13.31
],
"time_s": "2020-04-01T00:01:00+00:00"
},
"last_seen": {
"position": [
32.31,
11.24
],
"time_s": "2020-04-01T00:01:00+00:00"
},
"tags": [],
"time_s": "2020-04-01T00:01:00+00:00",
"zone_name": "conference-1"
},
{
"area": {
"concentrator_id": "c1",
"map_id": "m1",
"site_id": "s1"
},
"device_info": {
"manufacturer": "Apple",
"model": "iPhone 7",
"name": "Jane's iPhone 7",
"user": "Jane Doe"
},
"emitter": {
"network": {
"name": "Verizon"
},
"protocol": "LTE",
"transmitter_id": "vzw:1100:249:6f4d",
"vendor": "Unknown"
},
"event_id": "conference-1_LTE_vzw:1100:249:6f4d_s1_c1_m1_1585699320",
"event_type": "zone_event",
"first_seen": {
"position": [
34.61,
13.31
],
"time_s": "2020-04-01T00:02:00+00:00"
},
"last_seen": {
"position": [
32.31,
11.24
],
"time_s": "2020-04-01T00:02:00+00:00"
},
"tags": [],
"time_s": "2020-04-01T00:02:00+00:00",
"zone_name": "conference-1"
},
{
"area": {
"concentrator_id": "c1",
"map_id": "m1",
"site_id": "s1"
},
"device_info": {
"manufacturer": "Apple",
"model": "iPhone 7",
"name": "Jane's iPhone 7",
"user": "Jane Doe"
},
"emitter": {
"network": {
"name": "Verizon"
},
"protocol": "LTE",
"transmitter_id": "vzw:1100:249:6f4d",
"vendor": "Unknown"
},
"event_id": "conference-1_LTE_vzw:1100:249:6f4d_s1_c1_m1_1585699380",
"event_type": "zone_event",
"first_seen": {
"position": [
34.61,
13.31
],
"time_s": "2020-04-01T00:03:00+00:00"
},
"last_seen": {
"position": [
32.31,
11.24
],
"time_s": "2020-04-01T00:03:00+00:00"
},
"tags": [],
"time_s": "2020-04-01T00:03:00+00:00",
"zone_name": "conference-1"
},
{
"area": {
"concentrator_id": "c1",
"map_id": "m1",
"site_id": "s1"
},
"device_info": {
"manufacturer": "Apple",
"model": "iPhone 7",
"name": "Jane's iPhone 7",
"user": "Jane Doe"
},
"emitter": {
"network": {
"name": "Verizon"
},
"protocol": "LTE",
"transmitter_id": "vzw:1100:249:6f4d",
"vendor": "Unknown"
},
"event_id": "conference-1_LTE_vzw:1100:249:6f4d_s1_c1_m1_1585699440",
"event_type": "zone_event",
"first_seen": {
"position": [
34.61,
13.31
],
"time_s": "2020-04-01T00:04:00+00:00"
},
"last_seen": {
"position": [
32.31,
11.24
],
"time_s": "2020-04-01T00:04:00+00:00"
},
"tags": [],
"time_s": "2020-04-01T00:04:00+00:00",
"zone_name": "conference-1"
}
]
}
}
Human Readable Output
Zone Events
area device_info emitter event_id first_seen last_seen tags time_s zone_name site_id: s1
concentrator_id: c1
map_id: m1manufacturer: Apple
user: Jane Doe
model: iPhone 7
name: Jane’s iPhone 7protocol: LTE
transmitter_id: vzw:1100:249:6f4d
vendor: Unknown
network: {“name”: “Verizon”}conference-1_LTE_vzw:1100:249:6f4d_s1_c1_m1_1585699200 time_s: 2020-04-01T00:00:00+00:00
position: 34.61,
13.31position: 32.31,
11.24
time_s: 2020-04-01T00:00:00+00:002020-04-01T00:00:00+00:00 conference-1 site_id: s1
concentrator_id: c1
map_id: m1manufacturer: Apple
user: Jane Doe
model: iPhone 7
name: Jane’s iPhone 7protocol: LTE
transmitter_id: vzw:1100:249:6f4d
vendor: Unknown
network: {“name”: “Verizon”}conference-1_LTE_vzw:1100:249:6f4d_s1_c1_m1_1585699260 time_s: 2020-04-01T00:01:00+00:00
position: 34.61,
13.31position: 32.31,
11.24
time_s: 2020-04-01T00:01:00+00:002020-04-01T00:01:00+00:00 conference-1 site_id: s1
concentrator_id: c1
map_id: m1manufacturer: Apple
user: Jane Doe
model: iPhone 7
name: Jane’s iPhone 7protocol: LTE
transmitter_id: vzw:1100:249:6f4d
vendor: Unknown
network: {“name”: “Verizon”}conference-1_LTE_vzw:1100:249:6f4d_s1_c1_m1_1585699320 time_s: 2020-04-01T00:02:00+00:00
position: 34.61,
13.31position: 32.31,
11.24
time_s: 2020-04-01T00:02:00+00:002020-04-01T00:02:00+00:00 conference-1 site_id: s1
concentrator_id: c1
map_id: m1manufacturer: Apple
user: Jane Doe
model: iPhone 7
name: Jane’s iPhone 7protocol: LTE
transmitter_id: vzw:1100:249:6f4d
vendor: Unknown
network: {“name”: “Verizon”}conference-1_LTE_vzw:1100:249:6f4d_s1_c1_m1_1585699380 time_s: 2020-04-01T00:03:00+00:00
position: 34.61,
13.31position: 32.31,
11.24
time_s: 2020-04-01T00:03:00+00:002020-04-01T00:03:00+00:00 conference-1 site_id: s1
concentrator_id: c1
map_id: m1manufacturer: Apple
user: Jane Doe
model: iPhone 7
name: Jane’s iPhone 7protocol: LTE
transmitter_id: vzw:1100:249:6f4d
vendor: Unknown
network: {“name”: “Verizon”}conference-1_LTE_vzw:1100:249:6f4d_s1_c1_m1_1585699440 time_s: 2020-04-01T00:04:00+00:00
position: 34.61,
13.31position: 32.31,
11.24
time_s: 2020-04-01T00:04:00+00:002020-04-01T00:04:00+00:00 conference-1
bastille-add-device-tag
Command to add tag to an existing device
Base Command
bastille-add-device-tag
Input
| Argument Name | Description | Required |
|---|---|---|
| transmitter_id | Unique identifier of an existing admin devices entry | Required |
| tag | Tag to append to the admin devices entry | Required |
Context Output
There is no context output for this command.
Command Example
!bastille-add-device-tag transmitter_id=78:9f:70:7b:62:82 tag=test-tag
Context Example
{}
Human Readable Output
created
bastille-remove-device-tag
Command to remove tag from an existing device
Base Command
bastille-remove-device-tag
Input
| Argument Name | Description | Required |
|---|---|---|
| transmitter_id | Unique identifier of an existing admin devices entry | Required |
| tag | Tag to be removed from the admin devices entry | Required |
Context Output
There is no context output for this command.
Command Example
!bastille-remove-device-tag transmitter_id=78:9f:70:7b:62:82 tag=test-tag
Context Example
{}
Human Readable Output
updated
Configuration parameters
api_url— Server URLapi_key— API Key (required)site— Site (required)concentrator— Concentrator (required)map— Map (required)isFetch— Fetch incidentsincidentType— Incident typeincidentFetchInterval— Incidents Fetch Intervaltags— Tagsevent_types— Event types (required)first_fetch— First fetch timeinsecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (4)
-
bastille-add-device-tagCommand to add tag to an existing device
-
bastille-get-device-eventsCommand to fetch device detection events
-
bastille-get-zone-eventsCommand to fetch zone detection events
-
bastille-remove-device-tagCommand to remove tag from an existing device
import demistomock as demisto from CommonServerPython import * # noqa: E402 lgtm [py/polluting-import] from CommonServerUserPython import * # noqa: E402 lgtm [py/polluting-import] # IMPORTS import json import copy import urllib3 from datetime import datetime import dateparser # Disable insecure warnings urllib3.disable_warnings() # CONSTANTS DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ" MAX_INCIDENTS = 100 class Client(BaseClient): """Client to communicate with the Bastille service API""" @staticmethod def _build_event_query_params( site, concentrator, map, protocol=None, since=None, until=None, tags=None, event_id=None, limit=MAX_INCIDENTS ): """Build dictionary of common event query parameters""" if isinstance(since, datetime): since = str(since.timestamp()) if isinstance(until, datetime): until = str(until.timestamp()) params = {"site": site, "concentrator": concentrator, "map": map, "limit": limit} if protocol is not None: params["protocol"] = protocol if since is not None: params["since"] = since if until is not None: params["until"] = until if tags is not None: params["tags"] = tags if event_id is not None: params["event_id"] = event_id return params def get_zone_events( self, site, concentrator, map, zone=None, protocol=None, since=None, until=None, tags=None, event_id=None, limit=MAX_INCIDENTS, ): """Get detections that occurred in one given or all zones""" url_suffix = "/detection/zones" params = self._build_event_query_params(site, concentrator, map, protocol, since, until, tags, event_id, limit) if zone is not None: params["zone"] = zone return self._http_request(method="GET", url_suffix=url_suffix, params=params) def get_device_events( self, site, concentrator, map, transmitter_id=None, protocol=None, since=None, until=None, tags=None, event_id=None, limit=MAX_INCIDENTS, ): """Get device detection events for one given transmitter""" url_suffix = "/detection/devices" params = self._build_event_query_params(site, concentrator, map, protocol, since, until, tags, event_id, limit) params["transmitter_id"] = transmitter_id return self._http_request(method="GET", url_suffix=url_suffix, params=params) @staticmethod def _build_tag_action_body(site, concentrator, map, transmitter_id, tag): """Build dictionary of common device tagging action query body entries""" data = {"site": site, "concentrator": concentrator, "map": map, "transmitter_id": transmitter_id, "tag": tag} return data def add_device_tag(self, site, concentrator, map, transmitter_id, tag): """Add tag to a device""" url_suffix = "admin/devices/action.addTag" data = self._build_tag_action_body(site, concentrator, map, transmitter_id, tag) return self._http_request(method="POST", url_suffix=url_suffix, json_data=data) def remove_device_tag(self, site, concentrator, map, transmitter_id, tag): """Remove tag from an existing device""" url_suffix = "admin/devices/action.removeTag" data = self._build_tag_action_body(site, concentrator, map, transmitter_id, tag) return self._http_request(method="POST", url_suffix=url_suffix, json_data=data) def test_module(client): """Check connection to the Bastille API service""" try: site, concentrator, map = get_site_params() client.get_zone_events(limit=0, site=site, concentrator=concentrator, map=map) except DemistoException as exc: exc_msg = str(exc) if "[404]" in exc_msg or "ConnectionError" in exc_msg: result = "Server not found: check server URL" elif "[401]" in exc_msg or "[403]" in exc_msg: result = "Authorization error: check API key" elif "[500]" in exc_msg: result = "Internal server error" else: result = f"Unknown error {exc_msg}" else: result = "ok" return result def get_site_params(): """Helper to get the area related integration parameters""" params = demisto.params() site = params.get("site") concentrator = params.get("concentrator") map = params.get("map") return site, concentrator, map def get_event_args(args): """Helper to get the common event related command arguments""" protocol = args.get("protocol") since = args.get("since") until = args.get("until") limit = args.get("limit") tags = args.get("tags") event_id = args.get("event_id") if isinstance(since, str): since_date = dateparser.parse(since, settings={"TIMEZONE": "UTC"}) assert since_date is not None, f"failed parsing {since}" since = since_date.timestamp() if isinstance(until, str): until_date = dateparser.parse(until, settings={"TIMEZONE": "UTC"}) assert until_date is not None, f"failed parsing {until}" until = until_date.timestamp() return protocol, since, until, limit, tags, event_id def format_timestamp(timestamp): """Convert unix epoch to ISO formatted timestamp""" return datetime.utcfromtimestamp(timestamp).astimezone().isoformat() def parse_events(events, readable_fields): """Helper to parse common event command response""" for event in events: event["first_seen"] = { "time": format_timestamp(event["first_seen"]["time_s"]), "position": [round(p, 2) for p in event["first_seen"]["position"]], } if "last_seen" in event: event["last_seen"] = { "time": format_timestamp(event["last_seen"]["time_s"]), "position": [round(p, 2) for p in event["last_seen"]["position"]], } readable_events = [{f: e[f] for f in readable_fields} for e in events] return events, readable_events def get_zone_events_command(client, args): """Command to fetch zone events""" site, concentrator, map = get_site_params() protocol, since, until, limit, tags, event_id = get_event_args(args) zone = args.get("zone") events = client.get_zone_events( site=site, concentrator=concentrator, map=map, zone=zone, protocol=protocol, since=since, until=until, limit=limit, tags=tags, event_id=event_id, ) readable_fields = ["event_id", "area", "zone_name", "tags", "device_info", "emitter", "first_seen", "last_seen"] raw_response = copy.deepcopy(events) context_events, readable_events = parse_events(events, readable_fields) readable_output = tableToMarkdown("Zone Events", readable_events, readable_fields) context_output = {"Bastille.ZoneEvent(val.event_id == obj.event_id)": context_events} return readable_output, context_output, raw_response def get_device_events_command(client, args): """Command to fetch device detection events""" site, concentrator, map = get_site_params() protocol, since, until, limit, tags, event_id = get_event_args(args) transmitter_id = args.get("transmitter_id") events = client.get_device_events( site=site, concentrator=concentrator, map=map, protocol=protocol, since=since, until=until, limit=limit, tags=tags, event_id=event_id, transmitter_id=transmitter_id, ) readable_fields = ["event_id", "area", "tags", "device_info", "emitter", "first_seen", "last_seen"] raw_response = copy.deepcopy(events) context_events, readable_events = parse_events(events, readable_fields) readable_output = tableToMarkdown("Device Events", readable_events, readable_fields) context_output = {"Bastille.DeviceEvent(val.event_id == obj.event_id)": context_events} return readable_output, context_output, raw_response def add_device_tag_command(client, args): """Command to add tag to an existing admin devices entry""" site, concentrator, map = get_site_params() transmitter_id = args.get("transmitter_id") tag = args.get("tag") result = client.add_device_tag(site=site, concentrator=concentrator, map=map, transmitter_id=transmitter_id, tag=tag) if "status" not in result: return_error("Failed to add device tag") return result["status"], {}, result def remove_device_tag_command(client, args): """Command to remove tag from an existing admin devices entry""" site, concentrator, map = get_site_params() transmitter_id = args.get("transmitter_id") tag = args.get("tag") result = client.remove_device_tag(site=site, concentrator=concentrator, map=map, transmitter_id=transmitter_id, tag=tag) if "status" not in result: return_error("Failed to remove device tag") return result["status"], {}, result def fetch_incidents(client, last_run, first_fetch_time): """Callback to fetch incidents periodically""" last_fetch_time = last_run.get("last_fetch", first_fetch_time) site, concentrator, map = get_site_params() params = demisto.params() tags = params.get("tags") or None event_types = params.get("event_types") zone_events = [] if "all" in event_types or "zone_event" in event_types: zone_events = client.get_zone_events(concentrator=concentrator, map=map, site=site, tags=tags, since=last_fetch_time) device_events = [] if "all" in event_types or "device_event" in event_types: device_events = client.get_device_events(concentrator=concentrator, map=map, site=site, tags=tags, since=last_fetch_time) events = zone_events + device_events current_fetch_time = last_fetch_time incidents = [] for event in events: event_time = int(event["time_s"]) incident = { "name": event["event_type"], "occurred": datetime.utcfromtimestamp(event_time).strftime(DATE_FORMAT), "rawJSON": json.dumps(event), } if event_time > current_fetch_time: incidents.append(incident) if event_time > last_fetch_time: last_fetch_time = event_time next_run = {"last_fetch": last_fetch_time} return next_run, incidents def main(): """Parse and validate integration parameters""" params = demisto.params() api_url = urljoin(params["api_url"]) api_key = params.get("api_key") proxy = params.get("proxy", False) verify_certificate = not params.get("insecure", False) headers = { "Content-Type": "application/json", "x-api-key": api_key, } first_fetch_date = dateparser.parse(params.get("first_fetch", "5 minutes"), settings={"TIMEZONE": "UTC"}) assert first_fetch_date is not None first_fetch = first_fetch_date.timestamp() try: handle_proxy() client = Client(api_url, headers=headers, verify=verify_certificate, proxy=proxy) if demisto.command() == "test-module": result = test_module(client) demisto.results(result) elif demisto.command() == "fetch-incidents": next_run, incidents = fetch_incidents( client=client, last_run=demisto.getLastRun(), first_fetch_time=first_fetch, ) demisto.setLastRun(next_run) demisto.incidents(incidents) elif demisto.command() == "bastille-get-zone-events": results = get_zone_events_command(client, demisto.args()) return_outputs(*results) elif demisto.command() == "bastille-get-device-events": results = get_device_events_command(client, demisto.args()) return_outputs(*results) elif demisto.command() == "bastille-add-device-tag": results = add_device_tag_command(client, demisto.args()) return_outputs(*results) elif demisto.command() == "bastille-remove-device-tag": results = remove_device_tag_command(client, demisto.args()) return_outputs(*results) except Exception as e: return_error(f"Failed to execute {demisto.command()} command. Error: {str(e)}") if __name__ in ("__main__", "__builtin__", "builtins"): main()