KnowBe4 KMSAT Event Collector
KnowBe4_KMSAT allows you to push and pull your external data to and from the KnowBe4 console.
Analytics & SIEM · KMSAT
Details
| ID | KnowBe4 KMSAT Event Collector |
|---|---|
| Provider | Vista Equity Partners |
| Category | Analytics & SIEM |
| From Version | 6.8.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
Allows you to push and pull your external data to and from the KnowBe4 console.
Configure KnowBe4 KMSAT Event Collector in Cortex
| Parameter | Description | Required |
|---|---|---|
| Your server URL | True | |
| API Key | The API Key to use for connection. For more information about how to generate an API Key, refer to https://support.knowbe4.com/hc/en-us/articles/360024863474-User-Event-API | True |
| First fetch time interval | The time range to consider for the initial data fetch. (<number> <unit>, e.g., 2 days, 2 months, 2 years). Default is 1 day. | False |
| Events Fetch Interval | The Fetch interval. It is recommended to set it to 5 hours as there are not many events for this API and there’s an api-calls daily-limit for the basic API key. | False |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False |
Important Notes
The basic API-Key has a daily limit of calls per seat.
Therefore, the default and recommended Events Fetch Interval value is 5 hours and
First fetch time interval is 1 day.
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.
kms-get-events
Manual command to fetch events and display them.
Base Command
kms-get-events
Input
| Argument Name | Description | Required |
|---|---|---|
| occurred_date | Filter by the date the event occurred (YYYY-MM-DD). | Optional |
| risk_level | Filter by the risk level by entering a value from -10 (low risk) to 10 (high risk). | Optional |
| per_page | The number of results to display per page. The maximum and default is 100. | Optional |
| page | The results page to display. | Optional |
| should_push_events | Set this argument to True in order to create events, otherwise the command will only display them. If setting to ‘False’, the returned events will be lost. Possible values are: True, False. Default is False. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| KMSat.Event.id | Number | Event ID. |
| KMSat.Event.user.email | String | The target mail for this event. |
| KMSat.Event.user.id | Number | The ID of the user the event is targeted to. |
| KMSat.Event.user.archived | Boolean | Whether the user is archived or not. |
| KMSat.Event.external_id | String | The event’s external ID. |
| KMSat.Event.source | String | The source of the event. |
| KMSat.Event.description | String | The event description. |
| KMSat.Event.occurred_date | String | The date the event occurred. |
| KMSat.Event.risk.level | Number | The event’s risk level. |
| KMSat.Event.risk.factor | Number | The event’s risk factor. |
| KMSat.Event.risk.decay_mode | String | The risk’s decay mode. |
| KMSat.Event.risk.expire_date | String | The event’s expiration date. |
| KMSat.Event.event_type.id | Number | The ID of the event type. |
| KMSat.Event.event_type.name | String | The name of the event type. |
Command example
!kms-get-events should_push_events=false
Context Example
{
"KMSat": {
"Event": [
{
"account_id": 52306,
"description": "My description",
"event_type": {
"description": null,
"id": 418927900,
"name": "my_custom_event"
},
"external_id": null,
"id": "2b265035-1a12-4e76-bcb1-6c681b86333e",
"metadata": null,
"occurred_date": "2022-08-04T14:14:50.917Z",
"risk": {
"decay_mode": 0,
"expire_date": null,
"level": 5
},
"source": null,
"user": {
"archived": false,
"email": "example@example.com",
"id": 38651943
}
}
]
}
}
Human Readable Output
KnowBe4 KMSAT Logs
AccountId Description EventType Id OccurredDate Risk User 52306 My description lkjhy khl lgf id: 420899085
name: event_type_55
description: null786a515c-1cbd-4a8c-a94a-61ad877c893c 2022-08-09T10:05:13.890Z level: 5
decay_mode: 0
expire_date: nullemail: maizen@example.com
id: 38651943
archived: false52306 My description lkjhy khl lgf id: 420894024
name: event_type_2
description: nullc3081dfc-1bf9-4c56-b6ff-f364f0c13d39 2022-08-09T10:01:45.862Z level: 5
decay_mode: 0
expire_date: nullemail: maizen@example.com
id: 38651943
archived: false52306 My description id: 418927900
name: my_custom_event
description: null2b265035-1a12-4e76-bcb1-6c681b86333e 2022-08-04T14:14:50.917Z level: 5
decay_mode: 0
expire_date: nullemail: maizen@example.com
id: 38651943
archived: false
Configuration parameters
url— Your server URL (required)credentials— (required)first_fetch— First fetch time intervaleventFetchInterval— Events Fetch Intervalinsecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (1)
-
kms-get-eventsManual command to fetch and display events.
import datetime import json import pytest from CommonServerPython import parse_date_string from KnowBe4KMSATEventCollector import Client def util_load_json(path): with open(path, encoding="utf-8") as f: return json.loads(f.read()) MOCK_ENTRY = util_load_json("test_data/mock_event.json") BASE_URL = "https://api.events.knowbe4.com" def test_test_module(requests_mock): """ Given: - test-module call When: - A response with an OK status_code is retrieved from the API call. Then: - Make sure 'ok' is returned. """ from KnowBe4KMSATEventCollector import test_module requests_mock.get(f"{BASE_URL}/events", json=MOCK_ENTRY) assert test_module(Client(base_url=BASE_URL)) == "ok" @pytest.mark.parametrize( "last_run, mock_item, expected_last_run, expected_fetched_events", [ ( {"latest_event_time": "2022-08-05T10:05:03.000Z"}, MOCK_ENTRY, {"latest_event_time": "2022-08-09T10:05:13.890Z"}, MOCK_ENTRY.get("data", [])[0:-1], ), ( {"latest_event_time": parse_date_string("2022-08-05T10:05:03.000Z")}, MOCK_ENTRY, {"latest_event_time": "2022-08-09T10:05:13.890Z"}, MOCK_ENTRY.get("data", [])[0:-1], ), ], ) def test_fetch_events(requests_mock, last_run, mock_item, expected_last_run, expected_fetched_events): """ Given: - last_run marker and a mock with 2 events that occurred after the last run and 1 that occurred before. - case 1: The last run object is a string (an example of last run that was fetched from previous interval). - case 2: The last run object is a datetime object (an example of last run that was created by a default datetime.now() in the previous interval due to no fetched events). When: - Calling fetch events. Then: - Make sure 2 events returned. - Verify the new lastRun is calculated correctly. - Verify that the function handle the different last_run types correctly. """ from KnowBe4KMSATEventCollector import fetch_events requests_mock.get(f"{BASE_URL}/events", json=mock_item) events, new_last_run = fetch_events(Client(base_url=BASE_URL), last_run=last_run) assert expected_last_run == new_last_run assert events == expected_fetched_events assert len(events) == len(expected_fetched_events) @pytest.mark.parametrize( "last_run, fetched_events, expected_filtered_list_size, expected_filtered_list_elements", [ ( {"latest_event_time": datetime.datetime(2022, 5, 17, 10, 5, 3)}, [{"occurred_date": "2022-08-09T10:05:13.890Z"}], 1, [{"occurred_date": "2022-08-09T10:05:13.890Z"}], ), ({"latest_event_time": datetime.datetime(2022, 5, 17, 10, 5, 3)}, [{"occurred_date": "2022-03-09T10:05:13.890Z"}], 0, []), ( {"latest_event_time": datetime.datetime(2022, 5, 17, 10, 5, 3)}, [{"occurred_date": "2022-08-09T10:05:13.890Z"}, {"occurred_date": "2022-03-09T10:05:13.890Z"}], 1, [{"occurred_date": "2022-08-09T10:05:13.890Z"}], ), ], ) def test_eliminate_duplicated_events(last_run, fetched_events, expected_filtered_list_size, expected_filtered_list_elements): """ Given - A list of fetched events and a last_run date - Case 1: last_run object and a list with 1 event that occurred after the last_run. - Case 2: last_run object and a list with 1 event that occurred before the last_run. - Case 3: last_run object and a list with 1 event that occurred after the last_run and 1 event that occurred before it. When - Running eliminate_duplicated_events helper function. Then - Validate that all the events with the earlier than last_run 'occurred_date' are filtered out. - Case 1: Ensure that the event wasn't filtered out of the events list. - Case 2: Ensure that the event was filtered out of the events list. - Case 3: Ensure that the event that occurred after that last run wasn't filtered out of the events list and that the event that occurred before the last run was filtered. """ from KnowBe4KMSATEventCollector import eliminate_duplicated_events filtered_events_list = eliminate_duplicated_events(fetched_events, last_run) assert len(filtered_events_list) == expected_filtered_list_size for event in filtered_events_list: assert event in expected_filtered_list_elements @pytest.mark.parametrize( "last_run, events, expected_results", [ ({"latest_event_time": datetime.datetime(2022, 5, 17, 10, 5, 3)}, [{"occurred_date": "2022-08-09T10:05:13.890Z"}], False), ({"latest_event_time": datetime.datetime(2022, 5, 17, 10, 5, 3)}, [{"occurred_date": "2022-03-09T10:05:13.890Z"}], True), ], ) def test_check_if_last_run_reached(last_run, events, expected_results): """ Given - A list of fetched events and a last_run date. - Case 1: latest event that occurred before the first event in the events list. - Case 2: latest event that occurred after the first event in the events list. When - Running check_if_last_run_reached helper function. Then - Validate that the answer returend from the function is correct. - Case 1: Ensure that the function returned False. - Case 2: Ensure that the function returend True. """ from KnowBe4KMSATEventCollector import check_if_last_run_reached assert check_if_last_run_reached(last_run, events[0]) == expected_results @pytest.mark.parametrize( "mock_item, expected_results, expected_length", [(MOCK_ENTRY, MOCK_ENTRY.get("data", []), 3), ({}, "No events were found.", 21)], ) def test_get_events(requests_mock, mock_item, expected_results, expected_length): """ Given: - a mock response. - Case 1: A mock response with 3 events. - Case 2: Empty mock response. When: - Running the kms-get-events command. Then: - Make sure all of the events are returned as part of the CommandResult. - Case 1: Ensure the same 3 events were found. - Case 2: Should print that no events we found. """ from KnowBe4KMSATEventCollector import get_events_command requests_mock.get(f"{BASE_URL}/events", json=mock_item) args = {"should_push_events": False} results = get_events_command(Client(base_url=BASE_URL), args=args, vendor="", product="") if mock_item: assert results.outputs == expected_results assert len(results.outputs) == expected_length else: assert results.readable_output == expected_results assert len(results.readable_output) == expected_length