Beispiel #1
0
def _create_host_entities(data, geoip):
    """Create Host and IP Entities with GeoIP info."""
    for row in data.itertuples():
        host, ip_addr = row.Index
        if not host:
            continue
        host_ent = entities.Host(HostName=host)
        if not ip_addr:
            yield host_ent
            continue
        # If we have an IP address - get the IpAddress entity(ies)
        _, ip_entities = geoip.lookup_ip(ip_addr) if geoip else (None, [])
        if not ip_entities:
            host_ent.IpAddress = entities.IpAddress(Address=ip_addr)
            host_ent.IpAddress.FirstSeen = row.FirstSeen
            host_ent.IpAddress.LastSeen = row.LastSeen
        elif len(ip_entities) == 1:
            host_ent.IpAddress = ip_entities[0]
            host_ent.IpAddress.FirstSeen = row.FirstSeen
            host_ent.IpAddress.LastSeen = row.LastSeen
        else:
            host_ent.IpAddresses = []
            for ip_ent in ip_entities:
                ip_ent.FirstSeen = row.FirstSeen
                ip_ent.LastSeen = row.LastSeen
                host_ent.IpAddresses.append(ip_ent)

        yield host_ent
Beispiel #2
0
def get_heartbeat(
    qry_prov: QueryProvider, host_name: str = None, host_ip: str = None
) -> entities.Host:
    """
    Get Heartbeat information for host or IP.

    Parameters
    ----------
    qry_prov : QueryProvider
        Query provider to use for queries
    host_name : str, optional
        Host name, by default None
    host_ip : str, optional
        Host IP Address, by default None

    Returns
    -------
    Host
        Host entity

    """
    host_entity = entities.Host(HostName=host_name)
    if "Heartbeat" in qry_prov.schema_tables:
        nb_data_wait("Heartbeat")
        host_hb_df = None
        if host_name:
            host_hb_df = qry_prov.Network.get_heartbeat_for_host(host_name=host_name)
        elif host_ip:
            host_hb_df = qry_prov.Network.get_heartbeat_for_ip(ip_address=host_ip)
        if df_has_data(host_hb_df):
            host_entity = populate_host_entity(heartbeat_df=host_hb_df)

    return host_entity
def _create_host_entity(host_name=None, host_ip=None):
    host_entity = entities.Host()
    if host_name:
        host_entity.HostName = host_name
    if host_ip:
        ip_entity = entities.IpAddress(Address=host_ip)
        host_entity.IpAddress = ip_entity
    return host_entity
Beispiel #4
0
def populate_host_entity(
    heartbeat_df: pd.DataFrame = None,
    az_net_df: pd.DataFrame = None,
    vmcomputer_df: pd.DataFrame = None,
    host_entity: entities.Host = None,
    geo_lookup: Any = None,
) -> entities.Host:
    """
    Populate host with IP and other data.

    Parameters
    ----------
    heartbeat_df : pd.DataFrame
        A dataframe of heartbeat data for the host
    az_net_df : pd.DataFrame
        Optional dataframe of Azure network data for the host
    vmcomputer_df : pd.DataFrame
        Optional dataframe of VMComputer data for the host
    host_entity : Host
        Host entity in which to populate data. By default,
        a new host entity will be created.
    geo_lookup : Any
        GeoIP Provider to use, if needed.

    Returns
    -------
    Host
        How with details of the IP data collected

    """
    if host_entity is None:
        host_entity = entities.Host()

    ip_entities: List[entities.IpAddress] = []
    ip_unique: Set[str] = set()
    # Extract data from available dataframes
    if df_has_data(heartbeat_df):
        ip_hb = heartbeat_df.iloc[0]  # type: ignore
        ip_entity = _extract_heartbeat(ip_hb, host_entity)
        ip_entities.append(ip_entity)
        ip_unique.add(ip_entity.Address)

    if df_has_data(vmcomputer_df):
        ip_vm = vmcomputer_df.iloc[0]  # type: ignore
        _extract_vmcomputer(ip_vm, host_entity)
        ip_ents = convert_to_ip_entities(
            data=vmcomputer_df, ip_col="Ipv4Addresses", geo_lookup=geo_lookup
        )
        ip_entities.extend(
            ip_ent for ip_ent in ip_ents if ip_ent.Address not in ip_unique
        )
        ip_unique |= {ip_ent.Address for ip_ent in ip_ents}
        ip_ents = convert_to_ip_entities(
            data=vmcomputer_df, ip_col="Ipv6Addresses", geo_lookup=geo_lookup
        )
        ip_entities.extend(
            ip_ent for ip_ent in ip_ents if ip_ent.Address not in ip_unique
        )
        ip_unique |= {ip_ent.Address for ip_ent in ip_ents}

    # If Azure network data present add this to host record
    if df_has_data(az_net_df):
        if not host_entity.HostName:
            host_entity.HostName = az_net_df.iloc[0].Computer  # type: ignore
        ip_priv = convert_to_ip_entities(
            data=az_net_df, ip_col="PrivateIPAddresses", geo_lookup=geo_lookup
        )
        ip_pub = convert_to_ip_entities(
            data=az_net_df, ip_col="PublicIPAddresses", geo_lookup=geo_lookup
        )
        host_entity["PrivateIpAddresses"] = []
        host_entity["PrivateIpAddresses"].extend(
            ip_ent for ip_ent in ip_priv if ip_ent.Address not in ip_unique
        )
        host_entity["PublicIpAddresses"] = []
        host_entity["PublicIpAddresses"].extend(
            ip_ent for ip_ent in ip_pub if ip_ent.Address not in ip_unique
        )
        ip_entities.extend(host_entity["PrivateIpAddresses"])
        ip_entities.extend(host_entity["PublicIpAddresses"])

    host_entity["IpAddresses"] = ip_entities
    if not hasattr(host_entity, "IpAddress") and len(ip_entities) == 1:
        host_entity["IpAddress"] = ip_entities[0]

    return host_entity
Beispiel #5
0
    def run(
        self,
        value: Any = None,
        data: Optional[pd.DataFrame] = None,
        timespan: Optional[TimeSpan] = None,
        options: Optional[Iterable[str]] = None,
        **kwargs,
    ) -> HostSummaryResult:
        """
        Return host summary data.

        Parameters
        ----------
        value : str
            Host name
        data : Optional[pd.DataFrame], optional
            Not used, by default None
        timespan : TimeSpan
            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.
            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
        -------
        HostSummaryResult
            Result object with attributes for each result type.

        Raises
        ------
        MsticnbMissingParameterError
            If required parameters are missing

        """
        super().run(value=value,
                    data=data,
                    timespan=timespan,
                    options=options,
                    **kwargs)

        if not value:
            raise MsticnbMissingParameterError("value")
        if not timespan:
            raise MsticnbMissingParameterError("timespan.")

        self.timespan = timespan

        # pylint: disable=attribute-defined-outside-init
        result = HostSummaryResult(notebooklet=self,
                                   description=self.metadata.description,
                                   timespan=timespan)

        host_verif = verify_host_name(self.query_provider, value,
                                      self.timespan)
        if host_verif.host_names:
            md(f"Could not obtain unique host name from {value}. Aborting.")
            self._last_result = result
            return self._last_result
        if not host_verif.host_name:
            nb_markdown(
                f"Could not find event records for host {value}. " +
                "Results may be unreliable.",
                "orange",
            )
            host_name = value
        else:
            host_name = host_verif.host_name

        host_entity = entities.Host(HostName=host_name)
        if "heartbeat" in self.options:
            host_entity = get_heartbeat(self.query_provider, host_name)
        if "azure_net" in self.options:
            host_entity = host_entity or entities.Host(HostName=host_name)
            get_aznet_topology(self.query_provider,
                               host_entity=host_entity,
                               host_name=host_name)
        # If azure_details flag is set, an encrichment provider is given,
        # and the resource is an Azure host get resource details from Azure API

        if ("azure_api" in self.options
                and "azuredata" in self.data_providers.providers
                and ("Environment" in host_entity
                     and host_entity.Environment == "Azure")):
            azure_api = _azure_api_details(self.data_providers["azuredata"],
                                           host_entity)
            if azure_api:
                host_entity.AzureDetails["ResourceDetails"] = azure_api[
                    "resoure_details"]
                host_entity.AzureDetails["SubscriptionDetails"] = azure_api[
                    "sub_details"]

        result.host_entity = host_entity

        if not self.silent:
            _show_host_entity(host_entity)
        if "alerts" in self.options:
            related_alerts = _get_related_alerts(self.query_provider,
                                                 self.timespan, host_name)
            if len(related_alerts) > 0:
                result.alert_timeline = _show_alert_timeline(related_alerts)
            result.related_alerts = related_alerts

        if "bookmarks" in self.options:
            result.related_bookmarks = _get_related_bookmarks(
                self.query_provider, self.timespan, host_name)

        self._last_result = result
        return self._last_result