Пример #1
0
 def _get_timespan(self, timespan=None, **kwargs):
     if timespan:
         if isinstance(timespan, TimeSpan):
             self.timespan = timespan
         else:
             self.timespan = TimeSpan(timespan=timespan)
     elif "start" in kwargs and "end" in kwargs:
         self.timespan = TimeSpan(start=kwargs["start"], end=kwargs["end"])
Пример #2
0
def test_timespan_invalid_params():
    """Test error handling for invalid params."""
    period = timedelta(days=1)
    with pytest.raises(ValueError):
        TimeSpan()
    with pytest.raises(ValueError):
        TimeSpan(start="foo", period=period)
    with pytest.raises(ValueError):
        TimeSpan(start=None, end=None)
    with pytest.raises(ValueError):
        TimeSpan(period="some length")
    with pytest.raises(ValueError):
        TimeSpan(period=1)
Пример #3
0
def test_timespan_eq():
    """Test creating Timespan from another Timespan."""
    period = timedelta(days=1)
    tspan = TimeSpan(period=period)

    # Timespan object as a parameter
    tspan2 = TimeSpan(timespan=tspan)
    check.equal(tspan2, tspan)
    check.equal(hash(tspan2), hash(tspan))

    tspan2 = TimeSpan(timespan=(tspan.start, tspan.end))
    check.equal(tspan2, tspan)
    tspan2 = TimeSpan(timespan=(str(tspan.start), str(tspan.end)))
    check.equal(tspan2, tspan)
Пример #4
0
def test_timespan_parms():
    """Test standard parameters."""
    end = datetime.utcnow()
    period = timedelta(days=1)
    start = end - period
    tspan = TimeSpan(start=start, end=end)
    _validate_timespan(tspan, start, end)

    tspan = TimeSpan(end=end, period=period)
    _validate_timespan(tspan, start, end)

    tspan = TimeSpan(end=end, period="1D")
    _validate_timespan(tspan, start, end)

    tspan = TimeSpan(end=str(end), period="1D")
    _validate_timespan(tspan, start, end)

    tspan = TimeSpan(start=str(start), end=str(end))
    _validate_timespan(tspan, start, end)

    tspan = TimeSpan(start=str(start), period="1D")
    _validate_timespan(tspan, start, end)

    # end is set to utcnow()
    tspan = TimeSpan(start=start)
    _validate_timespan(tspan, start)

    # end is set to utcnow()
    tspan = TimeSpan(period=period)
    _validate_timespan(tspan, period=period)
Пример #5
0
def test_local_data(monkeypatch):
    """Test nblt output types and values using LocalData provider."""
    test_data = str(Path.cwd().joinpath(TEST_DATA_PATH))
    monkeypatch.setattr(data_providers, "GeoLiteLookup", GeoIPLiteMock)
    data_providers.init(
        query_provider="LocalData",
        LocalData_data_paths=[test_data],
        LocalData_query_paths=[test_data],
        providers=["tilookup", "geolitelookup"],
    )

    test_nblt = nblts.azsent.host.HostLogonsSummary()
    tspan = TimeSpan(start=datetime(2020, 6, 23, 4, 20),
                     end=datetime(2020, 6, 29, 21, 32))
    nbltlocaldata = test_nblt.run(value="WinAttackSim", timespan=tspan)
    assert isinstance(nbltlocaldata.logon_sessions, pd.DataFrame)
    assert nbltlocaldata.logon_sessions["SubjectUserName"].iloc[
        0] == "WinAttackSim$"
    assert nbltlocaldata.logon_sessions["LogonProcessName"].iloc[
        3] == "Advapi  "
    assert "User Pie Chart" in nbltlocaldata.plots.keys()
    assert isinstance(nbltlocaldata.plots["Process Bar Chart"], Figure)
    assert isinstance(nbltlocaldata.logon_matrix, pd.io.formats.style.Styler)
    assert nbltlocaldata.logon_matrix.index[0][0] == "Font Driver Host\\UMFD-0"
    assert isinstance(nbltlocaldata.logon_map, FoliumMap)
    assert isinstance(nbltlocaldata.timeline, Column)
def test_network_flow_summary_notebooklet(monkeypatch):
    """Test basic run of notebooklet."""
    test_data = str(Path(TEST_DATA_PATH).absolute())
    monkeypatch.setattr(data_providers, "GeoLiteLookup", GeoIPLiteMock)
    monkeypatch.setattr(data_providers, "TILookup", TILookupMock)
    data_providers.init(
        query_provider="LocalData",
        LocalData_data_paths=[test_data],
        LocalData_query_paths=[test_data],
    )

    test_nb = nblts.azsent.network.NetworkFlowSummary()
    tspan = TimeSpan(period="1D")

    test_nb.query_provider.schema.update({tab: {} for tab in DEF_PROV_TABLES})
    options = ["+geo_map"]
    result = test_nb.run(value="myhost", timespan=tspan, options=options)
    check.is_not_none(result.host_entity)
    check.is_not_none(result.network_flows)
    check.is_instance(result.network_flows, pd.DataFrame)
    check.is_not_none(result.plot_flows_by_protocol)
    check.is_instance(result.plot_flows_by_protocol, LayoutDOM)
    check.is_not_none(result.plot_flows_by_direction)
    check.is_instance(result.plot_flows_by_direction, LayoutDOM)
    check.is_not_none(result.plot_flow_values)
    check.is_instance(result.plot_flow_values, LayoutDOM)
    check.is_not_none(result.flow_index)
    check.is_instance(result.flow_summary, pd.DataFrame)

    result.select_asns()
    result.lookup_ti_for_asn_ips()
    result.show_selected_asn_map()
Пример #7
0
def test_template_notebooklet(monkeypatch):
    """Test basic run of notebooklet."""
    test_data = str(Path(TEST_DATA_PATH).absolute())
    monkeypatch.setattr(data_providers, "GeoLiteLookup", GeoIPLiteMock)
    data_providers.init(
        query_provider="LocalData",
        LocalData_data_paths=[test_data],
        LocalData_query_paths=[test_data],
    )

    test_nb = TemplateNB()
    tspan = TimeSpan(period="1D")

    result = test_nb.run(value="myhost", timespan=tspan)
    check.is_not_none(result.all_events)
    check.is_not_none(result.description)
    check.is_not_none(result.plot)

    result = test_nb.run(value="myhost",
                         timespan=tspan,
                         options=["+get_metadata"])
    check.is_not_none(result.additional_info)

    evts = test_nb.run_additional_operation(
        ["4679", "5058", "5061", "5059", "4776"])
    check.is_instance(evts, pd.DataFrame)
Пример #8
0
def test_ip_summary_notebooklet(monkeypatch):
    """Test basic run of notebooklet."""
    test_data = str(Path(TEST_DATA_PATH).absolute())
    monkeypatch.setattr(data_providers, "GeoLiteLookup", GeoIPLiteMock)
    monkeypatch.setattr(data_providers, "TILookup", TILookupMock)
    data_providers.init(
        query_provider="LocalData",
        LocalData_data_paths=[test_data],
        LocalData_query_paths=[test_data],
        providers=["tilookup", "geolitelookup"],
    )

    test_nb = nblts.azsent.network.IpAddressSummary()
    tspan = TimeSpan(period="1D")

    result = test_nb.run(value="11.1.2.3", timespan=tspan)
    check.is_not_none(result.ip_entity)
    check.equal(result.ip_type, "Public")
    check.equal(result.ip_origin, "External")
    check.is_in("CountryCode", result.geoip)
    check.is_not_none(result.location)
    check.is_not_none(result.notebooklet)
    check.is_not_none(result.whois)
    check.is_instance(result.related_alerts, pd.DataFrame)
    check.is_not_none(test_nb.browse_alerts())
    check.is_instance(result.passive_dns, pd.DataFrame)
    check.is_instance(result.ti_results, pd.DataFrame)
Пример #9
0
def test_winhostevents_notebooklet(monkeypatch):
    """Test basic run of notebooklet."""
    test_data = str(Path(TEST_DATA_PATH).absolute())
    monkeypatch.setattr(data_providers, "GeoLiteLookup", GeoIPLiteMock)
    data_providers.init(
        query_provider="LocalData",
        LocalData_data_paths=[test_data],
        LocalData_query_paths=[test_data],
    )

    test_nb = nblts.azsent.host.WinHostEvents()
    tspan = TimeSpan(period="1D")

    result = test_nb.run(value="myhost", timespan=tspan)
    check.is_not_none(result.all_events)
    check.is_instance(result.all_events, pd.DataFrame)
    check.is_not_none(result.event_pivot)
    check.is_instance(result.event_pivot, pd.DataFrame)
    check.is_not_none(result.account_events)
    check.is_instance(result.account_events, pd.DataFrame)
    check.is_not_none(result.event_pivot)
    check.is_instance(result.event_pivot, pd.DataFrame)
    # check.is_not_none(result.account_timeline)

    exp_events = test_nb.expand_events(["5058", "5061"])
    check.is_instance(exp_events, pd.DataFrame)
Пример #10
0
def test_ip_summary_notebooklet_internal(monkeypatch):
    """Test basic run of notebooklet."""
    test_data = str(Path(TEST_DATA_PATH).absolute())
    monkeypatch.setattr(data_providers, "GeoLiteLookup", GeoIPLiteMock)
    monkeypatch.setattr(data_providers, "TILookup", TILookupMock)
    data_providers.init(
        query_provider="LocalData",
        LocalData_data_paths=[test_data],
        LocalData_query_paths=[test_data],
        providers=["tilookup", "geolitelookup"],
    )

    test_nb = nblts.azsent.network.IpAddressSummary()
    tspan = TimeSpan(period="1D")

    test_nb.query_provider.schema.update({tab: {} for tab in DEF_PROV_TABLES})
    result = test_nb.run(value="40.76.43.124", timespan=tspan)
    check.is_not_none(result.ip_entity)
    check.equal(result.ip_type, "Public")
    check.equal(result.ip_origin, "Internal")
    check.is_not_none(result.whois)
    check.is_instance(result.related_alerts, pd.DataFrame)
    check.is_instance(result.heartbeat, pd.DataFrame)
    check.is_instance(result.az_network_if, pd.DataFrame)
    check.is_none(result.passive_dns)
    check.is_none(result.ti_results)
Пример #11
0
def test_misc_functions(_create_pivot_ns):
    """Test some additional methods of pivot.py."""
    check.greater(len(_create_pivot_ns.providers), 2)
    t_span = TimeSpan(end=datetime.utcnow(), period="1D")
    _create_pivot_ns.edit_query_time(timespan=t_span)
    check.equal(_create_pivot_ns.start, t_span.start)
    check.equal(_create_pivot_ns.end, t_span.end)
    check.equal(_create_pivot_ns.timespan, t_span)
Пример #12
0
def test_notebooklet_params(monkeypatch):
    """Test supplying timespan param."""
    monkeypatch.setattr(data_providers, "GeoLiteLookup", GeoIPLiteMock)
    data_providers.init(query_provider="LocalData",
                        providers=["tilookup", "geolitelookup"])
    test_nb = TstNBSummary()

    tspan = TimeSpan(period="1D")
    test_nb.run(timespan=tspan)
    check.equal(tspan, test_nb.timespan)

    test_nb.run(start=tspan.start, end=tspan.end)
    check.equal(tspan, test_nb.timespan)
Пример #13
0
def test_timespan_timeselector():
    """Test timespan with a time selector object."""
    end = datetime.utcnow()
    period = timedelta(days=1)
    start = end - period
    tspan = TimeSpan(period=period)

    # pylint: disable=too-few-public-methods
    class _TestTime:
        """Class to emulate QueryTimes widget. etc."""

        start = None
        end = None
        period = None

    test_t = _TestTime()
    test_t.start = start
    test_t.end = str(end)
    test_t.period = "1D"

    tspan = TimeSpan(timespan=test_t)
    _validate_timespan(tspan, start, end)
Пример #14
0
def test_pivot_time(data_providers):
    """Function_docstring."""
    providers = data_providers.values()
    end = datetime.utcnow()
    start = end - timedelta(1)
    timespan = TimeSpan(start=start, end=end)
    with warnings.catch_warnings():
        warnings.simplefilter("ignore", category=UserWarning)
        pivot = Pivot(providers=providers, timespan=timespan)
    check.equal(pivot.start, start)
    check.equal(pivot.end, end)

    end = end - timedelta(1)
    start = start - timedelta(1)
    # Test different ways of setting the time
    timespan = TimeSpan(start=start, end=end)
    pivot.timespan = timespan
    check.equal(pivot.start, start)
    check.equal(pivot.end, end)

    pivot.timespan = _TimeObj(start=timespan.start, end=timespan.end)
    check.equal(pivot.start, start)
    check.equal(pivot.end, end)

    pivot.set_timespan(timespan)
    check.equal(pivot.start, start)
    check.equal(pivot.end, end)

    pivot.set_timespan(start=timespan.start, end=timespan.end)
    check.equal(pivot.start, start)
    check.equal(pivot.end, end)

    # Make sure the values provided to queries match.
    _fake_provider_connected(data_providers["az_sent_prov"])

    query = entities.Host.AzureSentinel.SecurityEvent_list_host_processes(
        host_name="test", print=True)
    check.is_in(start.isoformat(), query)
    check.is_in(end.isoformat(), query)
Пример #15
0
def test_pivot_time(data_providers):
    """Function_docstring."""
    providers = data_providers.values()
    end = datetime.utcnow()
    start = end - timedelta(1)
    timespan = TimeSpan(start=start, end=end)
    pivot = Pivot(providers=providers, timespan=timespan)
    check.equal(pivot.start, start)
    check.equal(pivot.end, end)

    end = end - timedelta(1)
    start = start - timedelta(1)
    timespan = TimeSpan(start=start, end=end)
    pivot.timespan = timespan
    check.equal(pivot.start, start)
    check.equal(pivot.end, end)

    _fake_provider_connected(data_providers["az_sent_prov"])

    query = entities.Host.AzureSentinel.list_host_processes(host_name="test",
                                                            print_query=True)
    check.is_in(start.isoformat(), query)
    check.is_in(end.isoformat(), query)
Пример #16
0
def test_host_summary_notebooklet(monkeypatch):
    """Test basic run of notebooklet."""
    monkeypatch.setattr(data_providers, "GeoLiteLookup", GeoIPLiteMock)
    test_data = str(Path(TEST_DATA_PATH).absolute())
    data_providers.init(
        query_provider="LocalData",
        LocalData_data_paths=[test_data],
        LocalData_query_paths=[test_data],
    )

    test_nb = nblts.azsent.host.HostSummary()
    tspan = TimeSpan(period="1D")

    result = test_nb.run(value="myhost", timespan=tspan)
    check.is_not_none(result.host_entity)
    check.is_not_none(result.related_alerts)
    check.is_instance(result.related_alerts, pd.DataFrame)
    check.is_not_none(result.alert_timeline)
    check.is_not_none(result.related_bookmarks)
    check.is_instance(result.related_bookmarks, pd.DataFrame)
Пример #17
0
def test_ip_summary_notebooklet_all(monkeypatch):
    """Test basic run of notebooklet."""
    test_data = str(Path(TEST_DATA_PATH).absolute())
    monkeypatch.setattr(data_providers, "GeoLiteLookup", GeoIPLiteMock)
    monkeypatch.setattr(data_providers, "TILookup", TILookupMock)
    data_providers.init(
        query_provider="LocalData",
        LocalData_data_paths=[test_data],
        LocalData_query_paths=[test_data],
        providers=["tilookup", "geolitelookup"],
    )

    opts = ["+az_netflow", "+passive_dns", "+az_activity", "+office_365", "+ti"]
    test_nb = nblts.azsent.network.IpAddressSummary()
    tspan = TimeSpan(period="1D")
    test_nb.query_provider.schema.update({tab: {} for tab in DEF_PROV_TABLES})

    result = test_nb.run(value="40.76.43.124", timespan=tspan, options=opts)
    check.is_not_none(result.ip_entity)
    check.is_not_none(result.host_entity)
    check.equal(result.host_entity.HostName, "MSTICAlertsWin1")
    check.equal(result.host_entity.OSFamily.name, "Linux")
    check.equal(result.ip_type, "Public")
    check.equal(result.ip_origin, "Internal")
    check.is_instance(result.heartbeat, pd.DataFrame)
    check.is_instance(result.az_network_if, pd.DataFrame)
    check.is_instance(result.az_network_flows, pd.DataFrame)
    check.is_instance(result.az_network_flow_summary, pd.DataFrame)
    check.is_instance(result.az_network_flows_timeline, LayoutDOM)
    check.is_instance(result.aad_signins, pd.DataFrame)
    check.is_instance(result.office_activity, pd.DataFrame)
    check.is_instance(result.vmcomputer, pd.DataFrame)

    check.is_instance(test_nb.netflow_total_by_protocol(), LayoutDOM)
    check.is_instance(test_nb.netflow_by_direction(), LayoutDOM)

    check.is_not_none(result.whois)
    check.is_instance(result.related_alerts, pd.DataFrame)
    check.is_instance(result.passive_dns, pd.DataFrame)
    check.is_instance(result.ti_results, pd.DataFrame)
Пример #18
0
    def __init__(self,
                 data_providers: Optional[DataProviders] = None,
                 **kwargs):
        """
        Intialize a new instance of the notebooklet class.

        Parameters
        ----------
        data_providers : DataProviders, Optional
            Optional DataProviders instance to query data.
            Most classes require this.

        Raises
        ------
        MsticnbDataProviderError
            If DataProviders has not been initialized.
            If required providers are specified by the notebooklet
            but are not available.

        """
        self._kwargs = kwargs
        self.options: List[str] = self.default_options()
        self._set_tqdm_notebook(get_opt("verbose"))
        self._last_result: Any = None
        self.timespan = TimeSpan(period="1d")
        self._inst_default_silent: Optional[bool] = kwargs.get("silent")
        self._current_run_silent: Optional[bool] = None
        set_opt("temp_silent", self.silent)

        # update "run" function documentation on first run
        self._add_run_doc_options()

        # Check required data providers are loaded.
        # pylint: disable=no-member
        self.data_providers = data_providers or DataProviders.current(
        )  # type: ignore
        # pylint: enable=no-member
        self._check_nb_providers(**kwargs)
def _get_timespan():
    end = datetime.utcnow()
    return TimeSpan(start=(end - timedelta(1)), end=end)
Пример #20
0
def test_account_summary_notebooklet(monkeypatch):
    """Test basic run of notebooklet."""
    test_data = str(Path(TEST_DATA_PATH).absolute())
    monkeypatch.setattr(data_providers, "GeoLiteLookup", GeoIPLiteMock)
    data_providers.init(
        "LocalData",
        providers=["-tilookup"],
        LocalData_data_paths=[test_data],
        LocalData_query_paths=[test_data],
    )

    test_nb = nblts.azsent.account.AccountSummary()
    tspan = TimeSpan(period="1D")

    result = test_nb.run(value="accountname", timespan=tspan)
    check.is_not_none(result.account_selector)
    acct_select = test_nb.browse_accounts()
    check.is_instance(acct_select, nbwidgets.SelectItem)

    select_opts = result.account_selector._item_dict
    disp_account = result.account_selector.item_action
    for acct_item in select_opts.values():
        # Programatically select the item list control
        select_item = [
            key for key, value in select_opts.items() if value == acct_item
        ]
        if select_item:
            result.account_selector._wgt_select.value = select_item[0]
        disp_account(acct_item)
        check.is_instance(result.account_activity, pd.DataFrame)
        check.is_instance(result.related_alerts, pd.DataFrame)
        check.is_instance(result.related_bookmarks, pd.DataFrame)
        check.is_instance(result.alert_timeline, LayoutDOM)
        check.is_instance(result.account_entity, entities.Account)

        alert_select = test_nb.browse_alerts()
        check.is_instance(alert_select, nbwidgets.SelectAlert)
        bm_select = test_nb.browse_bookmarks()
        assert isinstance(bm_select, nbwidgets.SelectItem)

        test_nb.get_additional_data()

        check.is_instance(result.account_timeline_by_ip, LayoutDOM)
        if "Windows" in acct_item or "Linux" in acct_item:
            check.is_instance(result.host_logons, pd.DataFrame)
            check.is_instance(result.host_logon_summary, pd.DataFrame)
            check.is_none(result.azure_activity)
            check.is_none(result.azure_activity_summary)
            check.is_none(result.azure_timeline_by_provider)
            check.is_none(result.azure_timeline_by_operation)
            vwr = result.view_events(
                attrib="host_logons",
                summary_cols=["Computer", "LogonResult", "LogonType"],
            )
        else:
            check.is_none(result.host_logons)
            check.is_none(result.host_logon_summary)
            check.is_instance(result.azure_activity, pd.DataFrame)
            check.is_instance(result.azure_activity_summary, pd.DataFrame)
            check.is_instance(result.azure_timeline_by_provider, LayoutDOM)
            check.is_instance(result.azure_timeline_by_operation, LayoutDOM)
            vwr = result.view_events(
                attrib="azure_activity",
                summary_cols=["Source", "Operation", "IPAddress"],
            )
        check.is_instance(vwr, nbwidgets.SelectItem)

        result.display_alert_timeline()
        result.browse_accounts()
        result.browse_alerts()
        result.browse_bookmarks()
        result.az_activity_timeline_by_provider()
        result.az_activity_timeline_by_ip()
        result.az_activity_timeline_by_operation()
        result.host_logon_timeline()
        check.is_not_none(result.get_geoip_map())
Пример #21
0
    def run(
        self,
        value: Any = None,
        data: Optional[pd.DataFrame] = None,
        timespan: Optional[TimeSpan] = None,
        options: Optional[Iterable[str]] = None,
        **kwargs,
    ) -> NotebookletResult:
        """
        Notebooklet abstract base class.

        Parameters
        ----------
        value : Any, optional
            value to process, by default None
        data : Optional[pd.DataFrame], optional
            Input data to process, by default None
        timespan : Optional[TimeSpan, Any], optional
            Timespan over which operations such as queries will be
            performed, by default None.
            This can be a TimeStamp object or another object that
            has valid `start`, `end`, or `period` attributes.
        options :Optional[Iterable[str]], optional
            List of options to use, by default None
            A value of None means use default options.
            Options prefixed with "+" will be added to the default options.
            Options prefixed with "-" will be removed from the default options.
            To see the list of available options type `help(cls)` where
            "cls" is the notebooklet class or an instance of this class.

        Other Parameters
        ----------------
        start : Union[datetime, datelike-string]
            Alternative to specifying timespan parameter.
        end : Union[datetime, datelike-string]
            Alternative to specifying timespan parameter.

        Returns
        -------
        NotebookletResult
            Result class from the notebooklet

        See Also
        --------
            TimeSpan

        """
        self._current_run_silent = kwargs.get("silent")
        set_opt("temp_silent", self.silent)
        if not options:
            self.options = self.default_options()
        else:
            def_options = self.default_options()
            add_options = {opt[1:] for opt in options if opt.startswith("+")}
            sub_options = {opt[1:] for opt in options if opt.startswith("-")}
            std_options = {opt for opt in options if opt[0] not in ("+", "-")}
            if std_options and (add_options or sub_options):
                raise MsticnbError(
                    "Option list must be either a list of options to use",
                    "or options to add/remove from the default set.",
                    "You cannot mix these.",
                )
            invalid_opts = (sub_options | add_options | std_options) - set(
                self.all_options())
            if invalid_opts:
                print(f"Invalid options {list(invalid_opts)} ignored.")
            if sub_options:
                self.options = list(set(def_options) - sub_options)
            if add_options:
                self.options = list(set(def_options) | add_options)
            if not (add_options or sub_options):
                self.options = list(options)
        self._set_tqdm_notebook(get_opt("verbose"))
        if timespan:
            self.timespan = TimeSpan(timespan=timespan)
        elif "start" in kwargs and "end" in kwargs:
            self.timespan = TimeSpan(start=kwargs.get("start"),
                                     end=kwargs.get("end"))
        return NotebookletResult(notebooklet=self)