Skip to content

Commit

Permalink
Add pivot support for notebooklets run method.
Browse files Browse the repository at this point in the history
  • Loading branch information
ianhelle committed Jan 6, 2021
1 parent ee1125e commit 029753e
Show file tree
Hide file tree
Showing 16 changed files with 457 additions and 158 deletions.
2 changes: 2 additions & 0 deletions msticnb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
>>> # Interactive notebook browser
>>> nb.browse()
for more help see https://msticnb.readthedocs.org/
"""

from .data_providers import DataProviders, init # noqa:F401
Expand Down
6 changes: 2 additions & 4 deletions msticnb/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,8 @@ def text_wrapper(func):
def print_text(*args, **kwargs):
# "silent" can be global option or in the func kwargs
# The latter is only applicable for the NB run() method.
if "silent" in kwargs:
run_silent = kwargs.get("silent")
else:
run_silent = get_opt("silent")
run_silent = kwargs.get("silent") or get_opt("silent")

if not run_silent:
h_level = hd_level
out_title = title
Expand Down
56 changes: 36 additions & 20 deletions msticnb/nb/azsent/account/account_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from enum import Flag, auto
from typing import Any, Callable, Dict, Iterable, Optional, Union

import attr
import pandas as pd
from bokeh.io import show
from bokeh.models import LayoutDOM
Expand Down Expand Up @@ -66,8 +65,6 @@ def parse(cls, name: str):


# pylint: disable=too-few-public-methods, too-many-instance-attributes
# Rename this class
@attr.s(auto_attribs=True)
class AccountSummaryResult(NotebookletResult):
"""
Template Results.
Expand Down Expand Up @@ -101,20 +98,39 @@ class AccountSummaryResult(NotebookletResult):
"""

description: str = "Account Activity Summary"
account_entity: entities.Account = None
account_activity: pd.DataFrame = None
account_selector: nbwidgets.SelectItem = None
related_alerts: pd.DataFrame = None
alert_timeline: LayoutDOM = None
related_bookmarks: pd.DataFrame = None
host_logons: pd.DataFrame = None
host_logon_summary: pd.DataFrame = None
azure_activity: pd.DataFrame = None
azure_activity_summary: pd.DataFrame = None
azure_timeline_by_provider: LayoutDOM = None
account_timeline_by_ip: LayoutDOM = None
azure_timeline_by_operation: LayoutDOM = None
def __init__(
self,
description: Optional[str] = None,
timespan: Optional[TimeSpan] = None,
notebooklet: Optional["Notebooklet"] = None,
):
"""
Create new Notebooklet result instance.
Parameters
----------
description : Optional[str], optional
Result description, by default None
timespan : Optional[TimeSpan], optional
TimeSpan for the results, by default None
notebooklet : Optional[, optional
Originating notebooklet, by default None
"""
super().__init__(description, timespan, notebooklet)
self.description: str = "Account Activity Summary"
self.account_entity: entities.Account = None
self.account_activity: pd.DataFrame = None
self.account_selector: nbwidgets.SelectItem = None
self.related_alerts: pd.DataFrame = None
self.alert_timeline: LayoutDOM = None
self.related_bookmarks: pd.DataFrame = None
self.host_logons: pd.DataFrame = None
self.host_logon_summary: pd.DataFrame = None
self.azure_activity: pd.DataFrame = None
self.azure_activity_summary: pd.DataFrame = None
self.azure_timeline_by_provider: LayoutDOM = None
self.account_timeline_by_ip: LayoutDOM = None
self.azure_timeline_by_operation: LayoutDOM = None


# pylint: enable=too-few-public-methods
Expand Down Expand Up @@ -201,9 +217,9 @@ def run(
raise MsticnbMissingParameterError("timespan.")

# Create a result class
result = AccountSummaryResult()
result.description = self.metadata.description
result.timespan = timespan
result = AccountSummaryResult(
notebooklet=self, description=self.metadata.description, timespan=timespan
)
self.timespan = timespan
acc_types = kwargs.get("account_types")
if acc_types is None:
Expand Down
12 changes: 5 additions & 7 deletions msticnb/nb/azsent/account/o365_activity.yaml
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
metadata:
name: TemplateNB
description: Template YAML for Notebooklet
name: Office365Activity
description: Office 365 activity for an account
default_options:
- all_events: Gets all events about blah
- plot_events:
Display and summary and timeline of events.
other_options:
- get_metadata: fetches additional metadata about the entity
keywords:
- host
- computer
- heartbeat
- windows
- office
- azure
- account
entity_types:
- host
- account
req_providers:
- AzureSentinel|LocalData
- tilookup
Expand Down
46 changes: 31 additions & 15 deletions msticnb/nb/azsent/alert/ti_enrich.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import json
from typing import Any, Dict, Iterable, Optional

import attr
import pandas as pd
from IPython.display import display
from tqdm.notebook import tqdm
Expand Down Expand Up @@ -42,7 +41,6 @@

# pylint: disable=too-few-public-methods
# Rename this class
@attr.s(auto_attribs=True)
class TIEnrichResult(NotebookletResult):
"""
Template Results.
Expand All @@ -51,12 +49,33 @@ class TIEnrichResult(NotebookletResult):
----------
enriched_results : pd.DataFrame
Alerts with additional TI enrichment
picker : SelectAlert
Alert picker
"""

description: str = "Enriched Alerts"
enriched_results: pd.DataFrame = None
picker: SelectAlert = None
def __init__(
self,
description: Optional[str] = None,
timespan: Optional[TimeSpan] = None,
notebooklet: Optional["Notebooklet"] = None,
):
"""
Create new Notebooklet result instance.
Parameters
----------
description : Optional[str], optional
Result description, by default None
timespan : Optional[TimeSpan], optional
TimeSpan for the results, by default None
notebooklet : Optional[, optional
Originating notebooklet, by default None
"""
super().__init__(description, timespan, notebooklet)
self.description: str = "Enriched Alerts"
self.enriched_results: pd.DataFrame = None
self.picker: SelectAlert = None


# pylint: enable=too-few-public-methods
Expand Down Expand Up @@ -134,8 +153,9 @@ def run(
# Create a result class
# Add description to results for context
self._last_result = TIEnrichResult(
description=f"""Enriched alerts,
with the filter of {value}"""
description=f"""Enriched alerts with the filter of {value}""",
notebooklet=self,
timespan=timespan,
)

# Establish TI providers
Expand Down Expand Up @@ -256,10 +276,7 @@ def _get_all_alerts(qry_prov, timespan, filter_item=None):
end=timespan.end,
add_query_items=f'| where Entities contains "{filter_item}"',
)
else:
return qry_prov.SecurityAlert.list_alerts(
start=timespan.start, end=timespan.end
)
return qry_prov.SecurityAlert.list_alerts(start=timespan.start, end=timespan.end)


# Extract packed entity details
Expand Down Expand Up @@ -311,9 +328,8 @@ def _color_cells(val):
def _sev_score(sev):
if "high" in sev:
return "High"
elif "warning" in sev:
if "warning" in sev:
return "Warning"
elif "information" in sev:
if "information" in sev:
return "Information"
else:
return "None"
return "None"
68 changes: 43 additions & 25 deletions msticnb/nb/azsent/host/host_logons_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from math import pi
from typing import Any, Dict, Iterable, Optional

import attr
import pandas as pd
from bokeh.io import output_notebook
from bokeh.palettes import viridis # pylint: disable=no-name-in-module
Expand All @@ -17,7 +16,7 @@
from IPython.display import display
from msticpy.common.timespan import TimeSpan
from msticpy.nbtools import timeline
from msticpy.nbtools.foliummap import FoliumMap, get_center_ip_entities
from msticpy.nbtools.foliummap import FoliumMap
from msticpy.sectools.ip_utils import convert_to_ip_entities

from ...._version import VERSION
Expand All @@ -43,8 +42,8 @@
_CLS_METADATA, _CELL_DOCS = read_mod_metadata(__file__, __name__)


@attr.s(auto_attribs=True) # pylint: disable=too-few-public-methods
class HostLogonsSummaryResults(NotebookletResult):
# pylint: disable=too-few-public-methods
class HostLogonsSummaryResult(NotebookletResult):
"""
Host Logons Summary Results.
Expand All @@ -64,12 +63,31 @@ class HostLogonsSummaryResults(NotebookletResult):
"""

logon_sessions: pd.DataFrame = None
logon_matrix: pd.DataFrame = None
logon_map: FoliumMap = None
timeline: figure = None
failed_success: pd.DataFrame = None
plots: Optional[Dict[str, figure]] = None
def __init__(
self,
description: Optional[str] = None,
timespan: Optional[TimeSpan] = None,
notebooklet: Optional["Notebooklet"] = None,
):
"""
Create new Notebooklet result instance.
Parameters
----------
description : Optional[str], optional
Result description, by default None
timespan : Optional[TimeSpan], optional
TimeSpan for the results, by default None
notebooklet : Optional[, optional
Originating notebooklet, by default None
"""
super().__init__(description, timespan, notebooklet)
self.logon_sessions: pd.DataFrame = None
self.logon_matrix: pd.DataFrame = None
self.logon_map: FoliumMap = None
self.timeline: figure = None
self.failed_success: pd.DataFrame = None
self.plots: Optional[Dict[str, figure]] = None


class HostLogonsSummary(Notebooklet): # pylint: disable=too-few-public-methods
Expand Down Expand Up @@ -97,7 +115,7 @@ def run(
timespan: Optional[TimeSpan] = None,
options: Optional[Iterable[str]] = None,
**kwargs,
) -> HostLogonsSummaryResults:
) -> HostLogonsSummaryResult:
"""
Return host summary data.
Expand Down Expand Up @@ -171,8 +189,8 @@ def run(
data = _format_raw_data(data)

# Add description to results for context
self._last_result = HostLogonsSummaryResults(
description=self.metadata.description
self._last_result = HostLogonsSummaryResult(
notebooklet=self, description=self.metadata.description, timespan=timespan
)

# Check we have data
Expand Down Expand Up @@ -221,18 +239,18 @@ def _gen_timeline(data: pd.DataFrame, silent: bool):
],
hide=True,
)
else:
return timeline.display_timeline(
data[data["LogonResult"] != "Unknown"],
group_by="LogonResult",
source_columns=[
"Account",
"LogonProcessName",
"SourceIP",
"LogonTypeName",
"LogonResult",
],
)

return timeline.display_timeline(
data[data["LogonResult"] != "Unknown"],
group_by="LogonResult",
source_columns=[
"Account",
"LogonProcessName",
"SourceIP",
"LogonTypeName",
"LogonResult",
],
)


@set_text(docs=_CELL_DOCS, key="show_map")
Expand Down
Loading

0 comments on commit 029753e

Please sign in to comment.