diff --git a/CHANGELOG.md b/CHANGELOG.md index 28c4f4c77..02fb23286 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,6 +68,8 @@ - The 'json' option is no longer supported as the 'csv' option provides better performance (PR#2372 by elsif2). - `intelmq.bots.collectors.alienvault_otx.collector` (PR#2449 by qux-bbb): - Fix modified_pulses_only is always False. +- `intelmq.bots.collectors.shodan.collector_stream` (PR#x by Mikk Margus Möll): + - Add `alert` parameter to Shodan stream collector to allow fetching streams by configured alert ID #### Parsers diff --git a/docs/user/bots.md b/docs/user/bots.md index 791142dc2..b8a711309 100644 --- a/docs/user/bots.md +++ b/docs/user/bots.md @@ -994,6 +994,10 @@ Only the proxy is used (requires `shodan-python > 1.8.1`). Certificate is always () A list of countries to query for. If it is a string, it will be spit by `,`. +**`alert`** + +() Alert ID from monitor.shodan.io. + If the stream is interrupted, the connection will be aborted using the timeout parameter. No error will be logged if the number of consecutive connection fails does not reach the parameter `error_max_retries`. Instead of errors, an INFO message is logged. This is a measurement against too frequent ERROR diff --git a/intelmq/bots/collectors/shodan/collector_stream.py b/intelmq/bots/collectors/shodan/collector_stream.py index aeed4ff26..07eae1d8d 100644 --- a/intelmq/bots/collectors/shodan/collector_stream.py +++ b/intelmq/bots/collectors/shodan/collector_stream.py @@ -31,6 +31,7 @@ class ShodanStreamCollectorBot(CollectorBot): "Collect the Shodan stream from the Shodan API" api_key: str = "" countries: List[str] = [] + alert: str = '' def init(self): if shodan is None: @@ -46,14 +47,28 @@ def init(self): self.api = shodan.Shodan(self.api_key, proxies=self.proxy) if isinstance(self.countries, str): + if self.countries and self.alert: + raise ValueError('both alert and country filters specified in Shodan collector.') self.countries = self.countries.split(',') self.__error_count = 0 def process(self): try: - for line in self.api.stream.countries(timeout=self.http_timeout_sec, raw=True, - countries=self.countries): + if self.alert: + stream = self.api.stream.alert( + aid=self.alert, + timeout=self.http_timeout_sec, + raw=True, + ) + else: + stream = self.api.stream.countries( + countries=self.countries, + timeout=self.http_timeout_sec, + raw=True, + ) + + for line in stream: report = self.new_report() report.add('raw', line) self.send_message(report)