Skip to content

Commit 748769a

Browse files
committed
add new bot to fake data
1 parent adb2d15 commit 748769a

File tree

8 files changed

+137
-0
lines changed

8 files changed

+137
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
- `intelmq.bots.experts.securitytxt`:
4040
- Added new bot (PR#2538 by Frank Westers and Sebastian Wagner)
4141
- `intelmq.bots.experts.misp`: Use `PyMISP` class instead of deprecated `ExpandedPyMISP` (PR#2532 by Radek Vyhnal)
42+
- `intelmq.bots.experts.fake.expert`: New expert to fake data (PR#2567 by Sebastian Wagner).
4243

4344
#### Outputs
4445
- `intelmq.bots.outputs.cif3.output`:

docs/user/bots.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2734,6 +2734,39 @@ is `$portal_url + '/api/1.0/ripe/contact?cidr=%s'`.
27342734

27352735
---
27362736

2737+
### Fake <div id="intelmq.bots.experts.fake.expert" />
2738+
2739+
Adds fake data to events. Currently supports setting the IP address and network.
2740+
2741+
For each incoming event, the bots chooses one random IP network range from the configured data file.
2742+
It set's the first IP address of the range as `source.ip` and the network itself as `source.network`.
2743+
To adapt the `source.asn` field accordingly, use the [ASN Lookup Expert](#asn-lookup).
2744+
2745+
**Module:** `intelmq.bots.experts.fake.expert`
2746+
2747+
**Parameters:**
2748+
2749+
**`database`**
2750+
2751+
(required, string) Path to a JSON file in the following format:
2752+
```
2753+
{
2754+
"ip_network": [
2755+
"10.0.0.0/8",
2756+
...
2757+
]
2758+
}
2759+
```
2760+
2761+
**`overwrite`**
2762+
2763+
(optional, boolean) Whether to overwrite existing fields. Defaults to false.
2764+
2765+
For data consistency `source.network` will only be set if `source.ip` was set or overridden.
2766+
If overwrite is false, `source.ip` was did not exist before but `source.network` existed before, `source.network` will still be overridden.
2767+
2768+
---
2769+
27372770
### Field Reducer <div id="intelmq.bots.experts.field_reducer.expert" />
27382771

27392772
The field reducer bot is capable of removing fields from events.

intelmq/bots/experts/fake/__init__.py

Whitespace-only changes.

intelmq/bots/experts/fake/expert.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# SPDX-FileCopyrightText: 2025 Institute for Common Good Technology, Sebastian Wagner
2+
#
3+
# SPDX-License-Identifier: AGPL-3.0-or-later
4+
5+
from ipaddress import ip_network
6+
from random import choice
7+
from json import load as json_load
8+
9+
from intelmq.lib.bot import ExpertBot
10+
11+
12+
class FakeExpertBot(ExpertBot):
13+
"""Add fake data"""
14+
15+
overwrite: bool = False
16+
database: str = None # TODO: should be pathlib.Path
17+
18+
def init(self):
19+
with open(self.database) as database:
20+
self.networks = json_load(database)['ip_network']
21+
22+
def process(self):
23+
event = self.receive_message()
24+
network = choice(self.networks)
25+
26+
updated = False
27+
try:
28+
updated = event.add('source.ip', ip_network(network)[1], overwrite=self.overwrite)
29+
except IndexError:
30+
updated = event.add('source.ip', ip_network(network)[0], overwrite=self.overwrite)
31+
# For consistency, only set the network if the source.ip was set or overwritten, but then always overwrite it
32+
if updated:
33+
event.add('source.network', network, overwrite=True)
34+
35+
self.send_message(event)
36+
self.acknowledge_message()
37+
38+
def check(parameters: dict):
39+
try:
40+
with open(parameters['database']) as database:
41+
json_load(database)['ip_network']
42+
except Exception as exc:
43+
return [['error', exc]]
44+
45+
46+
BOT = FakeExpertBot

intelmq/tests/bots/experts/fake/__init__.py

Whitespace-only changes.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"ip_network": [
3+
"10.0.0.0/8"
4+
]
5+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
SPDX-FileCopyrightText: 2025 Institute for Common Good Technology, Sebastian Wagner
2+
SPDX-License-Identifier: AGPL-3.0-or-later
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# SPDX-FileCopyrightText: 2025 Institute for Common Good Technology, Sebastian Wagner
2+
#
3+
# SPDX-License-Identifier: AGPL-3.0-or-later
4+
5+
import unittest
6+
from json import loads as json_loads
7+
from ipaddress import ip_network, ip_address
8+
9+
import pkg_resources
10+
11+
import intelmq.lib.test as test
12+
from intelmq.bots.experts.fake.expert import FakeExpertBot
13+
14+
FAKE_DB = pkg_resources.resource_filename('intelmq', 'tests/bots/experts/fake/data.json')
15+
EXAMPLE_INPUT = {"__type": "Event",
16+
"source.ip": "93.184.216.34", # example.com
17+
}
18+
NETWOK_EXISTS = {"__type": "Event",
19+
"source.network": "93.184.216.0/24",
20+
}
21+
22+
class TestFakeExpertBot(test.BotTestCase, unittest.TestCase):
23+
24+
@classmethod
25+
def set_bot(cls):
26+
cls.bot_reference = FakeExpertBot
27+
cls.sysconfig = {'database': FAKE_DB}
28+
29+
def test_nochange(self):
30+
self.input_message = EXAMPLE_INPUT
31+
self.run_bot()
32+
self.assertMessageEqual(0, EXAMPLE_INPUT)
33+
34+
def test_overwrite(self):
35+
self.input_message = EXAMPLE_INPUT
36+
self.run_bot(parameters={'overwrite': True})
37+
msg = json_loads(self.get_output_queue()[0])
38+
self.assertIn(ip_address(msg['source.ip']), ip_network("10.0.0.0/8"))
39+
self.assertEqual(msg['source.network'], "10.0.0.0/8")
40+
41+
def test_network_exists(self):
42+
self.input_message = NETWOK_EXISTS
43+
self.run_bot(parameters={'overwrite': False})
44+
msg = json_loads(self.get_output_queue()[0])
45+
self.assertIn(ip_address(msg['source.ip']), ip_network("10.0.0.0/8"))
46+
self.assertEqual(msg['source.network'], "10.0.0.0/8")
47+
48+
49+
if __name__ == '__main__': # pragma: no cover
50+
unittest.main()

0 commit comments

Comments
 (0)