def custom_severity(self, sev_level): """Sets or removed the custom severity for this report. Arguments: sev_level (int): The new severity, or None to remove the custom severity. Returns: ReportSeverity (ReportSeverity): The new custom severity. None: If the custom severity was removed. Raises: InvalidObjectError: If `id` is missing or this Report is from a Watchlist. """ if not self.id: raise InvalidObjectError("missing report ID") if self._from_watchlist: raise InvalidObjectError( "watchlist reports don't have custom severities") url = "/threathunter/watchlistmgr/v3/orgs/{}/reports/{}/severity".format( self._cb.credentials.org_key, self.id) if sev_level is None: self._cb.delete_object(url) return args = { "report_id": self.id, "severity": sev_level, } resp = self._cb.put_object(url, args).json() return ReportSeverity(self._cb, initial_data=resp)
def validate(self): """Validates this IOC structure's state. Raises: InvalidObjectError: If the IOC structure's state is invalid. """ super(IOC, self).validate() for md5 in self.md5: if not validators(md5): raise InvalidObjectError( "invalid MD5 checksum: {}".format(md5)) for ipv4 in self.ipv4: if not validators(ipv4): raise InvalidObjectError( "invalid IPv4 address: {}".format(ipv4)) for ipv6 in self.ipv6: if not validators(ipv6): raise InvalidObjectError( "invalid IPv6 address: {}".format(ipv6)) for dns in self.dns: if not validators(dns): raise InvalidObjectError("invalid domain: {}".format(dns)) for query in self.query: if not self._cb.validate(query["search_query"]): raise InvalidObjectError("invalid search query: {}".format( query["search_query"]))
def ignored(self): """Returns the ignore status for this report. Only watchlist reports have an ignore status. Returns: (bool): True if this Report is ignored, False otherwise. Raises: InvalidObjectError: If `id` is missing or this Report is not from a Watchlist. Example: >>> if report.ignored: ... report.unignore() """ if not self.id: raise InvalidObjectError("missing Report ID") if not self._from_watchlist: raise InvalidObjectError( "ignore status only applies to watchlist reports") url = "/threathunter/watchlistmgr/v3/orgs/{}/reports/{}/ignore".format( self._cb.credentials.org_key, self.id) resp = self._cb.get_object(url) return resp["ignored"]
def update(self, **kwargs): """Update this Report with the given arguments. Arguments: **kwargs (dict(str, str)): The Report fields to update. Returns: Report (Report): The updated Report. Raises: InvalidObjectError: If `id` is missing, or `feed_id` is missing and this report is a Feed Report, or Report.validate() fails. Note: The report's timestamp is always updated, regardless of whether passed explicitly. >>> report.update(title="My new report title") """ if not self.id: raise InvalidObjectError("missing Report ID") if self._from_watchlist: url = "/threathunter/watchlistmgr/v3/orgs/{}/reports/{}".format( self._cb.credentials.org_key, self.id) else: if not self._feed_id: raise InvalidObjectError("missing Feed ID") url = "/threathunter/feedmgr/v2/orgs/{}/feeds/{}/reports/{}".format( self._cb.credentials.org_key, self._feed_id, self.id) for key, value in kwargs.items(): if key in self._info: self._info[key] = value if self.iocs: self._iocs = IOC(self._cb, initial_data=self.iocs, report_id=self.id) if self.iocs_v2: self._iocs_v2 = [ IOC_V2(self._cb, initial_data=ioc, report_id=self.id) for ioc in self.iocs_v2 ] # NOTE(ww): Updating reports on the watchlist API appears to require # updated timestamps. self.timestamp = int(time.time()) self.validate() new_info = self._cb.put_object(url, self._info).json() self._info.update(new_info) return self
def update(self, **kwargs): """Update this feed's metadata with the given arguments. Arguments: **kwargs (dict(str, str)): The fields to update. Raises: InvalidObjectError: If `id` is missing or Feed.validate() fails. ApiError: If an invalid field is specified. Example: >>> feed.update(access="private") """ if not self.id: raise InvalidObjectError("missing feed ID") for key, value in kwargs.items(): if key in self._info: self._info[key] = value self.validate() url = "/threathunter/feedmgr/v2/orgs/{}/feeds/{}/feedinfo".format( self._cb.credentials.org_key, self.id, ) new_info = self._cb.put_object(url, self._info).json() self._info.update(new_info) return self
def validate(self): """Validates this feed's state. Raises: InvalidObjectError: If the Feed's state is invalid. """ super(Feed, self).validate() if self.access not in ["public", "private"]: raise InvalidObjectError("access should be public or private") if not validators.url(self.provider_url): raise InvalidObjectError("provider_url should be a valid URL") for report in self._reports: report.validate()
def download_url(self, expiration_seconds=3600): """Returns a URL that can be used to download the file for this binary. Returns None if no download found. Arguments: expiration_seconds (int): How long the download should be valid for. Returns: URL (str): A pre-signed AWS download URL. None: If no download is found. Raises: InvalidObjectError: If the URL retrieval should be retried. """ downloads = self._cb.select(Downloads, [self.sha256], expiration_seconds=expiration_seconds) if self.sha256 in downloads.not_found: return None elif self.sha256 in downloads.error: raise InvalidObjectError("{} should be retried".format( self.sha256)) else: return next( (item.url for item in downloads.found if self.sha256 == item.sha256), None)
def unignore(self): """Removes the ignore status on this IOC. Only watchlist IOCs have an ignore status. Raises: InvalidObjectError: If `id` is missing or this IOC is not from a Watchlist. """ if not self.id: raise InvalidObjectError("missing Report ID") if not self._report_id: raise InvalidObjectError("ignoring only applies to watchlist IOCs") url = "/threathunter/watchlistmgr/v3/orgs/{}/reports/{}/iocs/{}/ignore".format( self._cb.credentials.org_key, self._report_id, self.id) self._cb.delete_object(url)
def update(self, **kwargs): """Updates this watchlist with the given arguments. Arguments: **kwargs (dict(str, str)): The fields to update. Raises: InvalidObjectError: If `id` is missing or Watchlist.validate() fails. ApiError: If `report_ids` is given and is empty. Example: >>> watchlist.update(name="New Name") """ if not self.id: raise InvalidObjectError("missing Watchlist ID") # NOTE(ww): Special case, according to the docs. if "report_ids" in kwargs and not kwargs["report_ids"]: raise ApiError( "can't update a watchlist to have an empty report list") for key, value in kwargs.items(): if key in self._info: self._info[key] = value self.validate() url = "/threathunter/watchlistmgr/v3/orgs/{}/watchlists/{}".format( self._cb.credentials.org_key, self.id) new_info = self._cb.put_object(url, self._info).json() self._info.update(new_info)
def ignore(self): """Sets the ignore status on this report. Only watchlist reports have an ignore status. Raises: InvalidObjectError: If `id` is missing or this Report is not from a Watchlist. """ if not self.id: raise InvalidObjectError("missing Report ID") if not self._from_watchlist: raise InvalidObjectError( "ignoring only applies to watchlist reports") url = "/threathunter/watchlistmgr/v3/orgs/{}/reports/{}/ignore".format( self._cb.credentials.org_key, self.id) self._cb.put_object(url, None)
def validate(self): """Validates this IOC_V2's state. Raises: InvalidObjectError: If the IOC_V2's state is invalid. """ super(IOC_V2, self).validate() if self.link and not validators.url(self.link): raise InvalidObjectError("link should be a valid URL")
def custom_severity(self): """Returns the custom severity for this report. Returns: ReportSeverity (ReportSeverity): The custom severity for this Report, if it exists. Raises: InvalidObjectError: If `id` ismissing or this Report is from a Watchlist. """ if not self.id: raise InvalidObjectError("missing report ID") if self._from_watchlist: raise InvalidObjectError( "watchlist reports don't have custom severities") url = "/threathunter/watchlistmgr/v3/orgs/{}/reports/{}/severity".format( self._cb.credentials.org_key, self.id) resp = self._cb.get_object(url) return ReportSeverity(self._cb, initial_data=resp)
def enable_alerts(self): """Enable alerts for this watchlist. Alerts are not retroactive. Raises: InvalidObjectError: If `id` is missing. """ if not self.id: raise InvalidObjectError("missing Watchlist ID") url = "/threathunter/watchlistmgr/v3/orgs/{}/watchlists/{}/alert".format( self._cb.credentials.org_key, self.id) self._cb.put_object(url, None)
def delete(self): """Deletes this feed from the Enterprise EDR server. Raises: InvalidObjectError: If `id` is missing. """ if not self.id: raise InvalidObjectError("missing feed ID") url = "/threathunter/feedmgr/v2/orgs/{}/feeds/{}".format( self._cb.credentials.org_key, self.id) self._cb.delete_object(url)
def disable_tags(self): """Disable tagging for this watchlist. Raises: InvalidObjectError: if `id` is missing. """ if not self.id: raise InvalidObjectError("missing Watchlist ID") url = "/threathunter/watchlistmgr/v3/orgs/{}/watchlists/{}/tag".format( self._cb.credentials.org_key, self.id) self._cb.delete_object(url)
def validate(self): """Validates this report's state. Raises: InvalidObjectError: If the report's state is invalid """ super(Report, self).validate() if self.link and not validators.url(self.link): raise InvalidObjectError("link should be a valid URL") if self.iocs_v2: [ioc.validate() for ioc in self._iocs_v2]
def ignored(self): """Returns whether or not this IOC is ignored Returns: (bool): True if the IOC is ignore, False otherwise. Raises: InvalidObjectError: If this IOC is missing an `id` or is not a Watchlist IOC. Example: >>> if ioc.ignored: ... ioc.unignore() """ if not self.id: raise InvalidObjectError("missing IOC ID") if not self._report_id: raise InvalidObjectError( "ignore status only applies to watchlist IOCs") url = "/threathunter/watchlistmgr/v3/orgs/{}/reports/{}/iocs/{}/ignore".format( self._cb.credentials.org_key, self._report_id, self.id) resp = self._cb.get_object(url) return resp["ignored"]
def delete(self): """Deletes this report from the Enterprise EDR server. Raises: InvalidObjectError: If `id` is missing, or `feed_id` is missing and this report is a Feed Report. Example: >>> report.delete() """ if not self.id: raise InvalidObjectError("missing Report ID") if self._from_watchlist: url = "/threathunter/watchlistmgr/v3/orgs/{}/reports/{}".format( self._cb.credentials.org_key, self.id) else: if not self._feed_id: raise InvalidObjectError("missing Feed ID") url = "/threathunter/feedmgr/v2/orgs/{}/feeds/{}/reports/{}".format( self._cb.credentials.org_key, self._feed_id, self.id) self._cb.delete_object(url)
def replace_reports(self, reports): """Replace this Feed's Reports with the given Reports. Arguments: reports ([Report]): List of Reports to replace existing Reports with. Raises: InvalidObjectError: If `id` is missing. """ if not self.id: raise InvalidObjectError("missing feed ID") rep_dicts = [report._info for report in reports] body = {"reports": rep_dicts} url = "/threathunter/feedmgr/v2/orgs/{}/feeds/{}/reports".format( self._cb.credentials.org_key, self.id) self._cb.post_object(url, body)
def append_reports(self, reports): """Append the given Reports to this Feed's current Reports. Arguments: reports ([Report]): List of Reports to append to Feed. Raises: InvalidObjectError: If `id` is missing. """ if not self.id: raise InvalidObjectError("missing feed ID") rep_dicts = [report._info for report in reports] rep_dicts += [report._info for report in self.reports] body = {"reports": rep_dicts} url = "/threathunter/feedmgr/v2/orgs/{}/feeds/{}/reports".format( self._cb.credentials.org_key, self.id) self._cb.post_object(url, body)