Path: blob/master/src/SentinelUtilities/SentinelPortal/bookmark_helper.py
3255 views
# -------------------------------------------------------------------------1# Copyright (c) Microsoft Corporation. All rights reserved.2# Licensed under the MIT License. See License.txt in the project root for3# license information.4# --------------------------------------------------------------------------5"""6Hunting Bookmark Helper:7This module provides helper methods to initialize and8manipulate Hunting Bookmark (create, read, and delete).9"""10# pylint: disable-msg=C010311# pylint: disable-msg=E040112# pylint: disable-msg=E060213# pylint: disable-msg=R090214# pylint: disable-msg=R090315# pylint: disable-msg=R091316# pylint: disable-msg=W020117# pylint: disable=line-too-long1819import uuid20import requests21import jsons22from SentinelUtils import InputValidation232425class Constants():26""" This class holds constants """27TYPE = 'Microsoft.SecurityInsights/Bookmarks'28ETAG = '*'29BOOKMARK_RESOURCE_BASE = '/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.OperationalInsights/workspaces/{2}/providers/Microsoft.SecurityInsights/bookmarks'30BOOKMARK_ID = '/{0}'31BOOKMARK_RESOURCE_ID = BOOKMARK_RESOURCE_BASE + BOOKMARK_ID32ENTITY_MAPPING = '__entityMapping'33ENTITY_TYPE = ['Bookmark'34'SecurityAlert',35'Account',36'Host',37'Malware',38'File',39'Process',40'CloudApplication',41'DnsResolution',42'AzureResource',43'FileHash',44'RegistryKey',45'RegistryValue',46'SecurityGroup',47'Url']484950class BookmarkProperties():51"""52This class holds properties for Hunting bookmark.53Special Note: For query_result_dict, actual value is the key, and the entity type is the value.54"""5556def __init__(self,57display_name,58query,59query_result_dict=None,60tag_list=None,61notes=None,62event_time=None,63query_start_time=None,64query_end_time=None):65self.displayName = display_name66self.labels = tag_list67self.query = query68self.queryResult = query_result_dict69self.notes = notes70self.eventTime = event_time71self.queryStartTime = query_start_time72self.queryEndTime = query_end_time73self.bookmarkId = str(uuid.uuid4())7475@property76def bookmarkId(self):77""" bookmarkId getter """78return self._bookmarkId7980@bookmarkId.setter81def bookmarkId(self, bookmark_id):82""" bookmarkId setter """83self._bookmarkId = bookmark_id8485@property86def displayName(self):87""" displayName getter """88return self._displayName8990@displayName.setter91def displayName(self, display_name):92""" displayName setter """93InputValidation.validate_input('display_name', display_name)94self._displayName = display_name9596@property97def labels(self):98""" labels getter """99return self._labels100101@labels.setter102def labels(self, tag_list):103""" labels setter """104if tag_list:105self._labels = tag_list106else:107self._labels = []108109@property110def query(self):111""" query """112return self._query113114@query.setter115def query(self, query):116""" query setter """117InputValidation.validate_input('query', query)118self._query = query119120@property121def queryResult(self):122""" queryResult """123return self._queryResult124125@queryResult.setter126def queryResult(self, query_result):127""" queryResult setter """128result_str = None129if query_result and isinstance(query_result, dict):130if all(elem in Constants.ENTITY_TYPE for elem in list(query_result.values())):131query_result_dict = {}132query_result_dict.update({Constants.ENTITY_MAPPING: query_result})133result_str = jsons.dumps(query_result_dict)134self._queryResult = result_str135if not result_str:136self._queryResult = '{}'137138@property139def notes(self):140""" notes getter """141return self._notes142143@notes.setter144def notes(self, notes):145""" notes setter """146self._notes = notes147148@property149def eventTime(self):150""" eventTime """151return self._eventTime152153@eventTime.setter154def eventTime(self, event_time):155""" eventTime setter """156self._eventTime = event_time157158@property159def queryStartTime(self):160""" queryStartTime """161return self._queryStartTime162163@queryStartTime.setter164def queryStartTime(self, query_start_time):165""" queryStartTime setter """166self._queryStartTime = query_start_time167168@property169def queryEndTime(self):170""" queryEndTime """171return self._queryEndTime172173@queryEndTime.setter174def queryEndTime(self, query_end_time):175""" queryEndTime setter """176self._queryEndTime = query_end_time177178179class BookmarkModel():180""" This class holds data model for Bookmark """181182def __init__(self,183bookmark_name,184subscription_id,185resource_group_name,186workspace_name,187bookmark_properties):188self.name = bookmark_name189self.type = Constants.TYPE190self.etag = Constants.ETAG191self.properties = bookmark_properties192self.bookmark_resource_base = Constants.BOOKMARK_RESOURCE_BASE.format(subscription_id, resource_group_name, workspace_name)193self.id = self.bookmark_resource_base + Constants.BOOKMARK_ID.format(bookmark_properties.bookmarkId)194195@property196def id(self):197""" id getter """198return self._id199200@id.setter201def id(self, bookmark_resource_id):202""" id setter """203self._id = bookmark_resource_id204205@property206def name(self):207""" name getter """208return self._name209210@name.setter211def name(self, bookmark_name):212""" name setter """213InputValidation.validate_input('bookmark_name', bookmark_name)214self._name = bookmark_name215216@property217def type(self):218""" type getter """219return self._type220221@type.setter222def type(self, t):223""" type setter """224self._type = t225226@property227def etag(self):228""" etag getter """229return self._etag230231@etag.setter232def etag(self, etag):233""" etag setter """234self._etag = etag235236@property237def properties(self):238""" properties getter """239return self._properties240241@properties.setter242def properties(self, bookmark_properties):243""" properties setter """244InputValidation.validate_input('bookmark_properties', bookmark_properties)245self._properties = bookmark_properties246247# pylint: disable-msg=W0703248class BookmarkHelper:249""" This class provides CRUD methods for bookmark """250251BOOKMARK_BASE_URL = 'https://management.azure.com'252BOOKMARK_API_VERSION = '?api-version=2019-01-01-preview'253254def __init__(self, access_token):255self.access_token = access_token256257def _set_header(self):258return {'Authorization': 'Bearer ' + self.access_token}259260def _set_rp_put_url(self, bookmark_model):261return self.BOOKMARK_BASE_URL + bookmark_model.id + self.BOOKMARK_API_VERSION262263def _set_rp_get_url(self, bookmark_model):264return self.BOOKMARK_BASE_URL + bookmark_model.bookmark_resource_base + self.BOOKMARK_API_VERSION265266def _set_rp_delete_url(self, bookmark_model):267return self.BOOKMARK_BASE_URL + bookmark_model.id + self.BOOKMARK_API_VERSION268269def _generate_bookmark_payload(self, bookmark_model):270items = jsons.dump(bookmark_model, strip_privates=True)271return jsons.dump(self._cleanup_json(items))272273def _cleanup_json(self, data):274"""275Delete keys with the value ``None`` in a dictionary, recursively.276This alters the input so you may wish to ``copy`` the dict first.277"""278for key, value in list(data.items()):279if key == 'bookmark_resource_base':280del data[key]281elif value is None:282del data[key]283elif isinstance(value, dict):284self._cleanup_json(value)285286return data287288def add_bookmark(self, bookmark_model):289""" Create a hunting bookmark """290try:291result = requests.put(292self._set_rp_put_url(bookmark_model),293headers=self._set_header(),294json=self._generate_bookmark_payload(bookmark_model))295print('Success')296return result297except Exception as e:298print(str(e))299300def get_bookmarks(self, bookmark_model):301""" Retrieve hunting bookmarks for workspace """302try:303result = requests.get(304self._set_rp_get_url(bookmark_model),305headers=self._set_header())306print('Success')307return result308except Exception as e:309print(str(e))310311def delete_bookmark(self, bookmark_model):312""" Delete a hunting bookmark, not recommend for notebook users """313try:314result = requests.delete(315self._set_rp_delete_url(bookmark_model),316headers=self._set_header())317print('Success')318return result319except Exception as e:320print(str(e))321322# end of the class323324325