Skip to content

Commit 27f5536

Browse files
committed
Deprecate and remove TalosReputation. Closes #3451
1 parent b4f242a commit 27f5536

File tree

7 files changed

+137
-105
lines changed

7 files changed

+137
-105
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl
2+
# See the file 'LICENSE' for copying permission.
3+
4+
5+
from django.db import migrations
6+
7+
8+
def _cleanup_schedule(schedule, field_name, PeriodicTask, PythonModule, is_crontab):
9+
"""Delete a schedule if it is no longer referenced by any task or module."""
10+
if schedule is None:
11+
return
12+
still_used = PeriodicTask.objects.filter(**{field_name: schedule}).exists()
13+
if not still_used and is_crontab:
14+
still_used = (
15+
PythonModule.objects.filter(update_schedule=schedule).exists()
16+
or PythonModule.objects.filter(health_check_schedule=schedule).exists()
17+
)
18+
if not still_used:
19+
try:
20+
schedule.delete()
21+
except Exception:
22+
pass # Another model (e.g. IngestorConfig) may still reference this schedule
23+
24+
25+
def remove_talos_forward(apps, schema_editor):
26+
AnalyzerConfig = apps.get_model("analyzers_manager", "AnalyzerConfig")
27+
PythonModule = apps.get_model("api_app", "PythonModule")
28+
PeriodicTask = apps.get_model("django_celery_beat", "PeriodicTask")
29+
IntervalSchedule = apps.get_model("django_celery_beat", "IntervalSchedule")
30+
CrontabSchedule = apps.get_model("django_celery_beat", "CrontabSchedule")
31+
SolarSchedule = apps.get_model("django_celery_beat", "SolarSchedule")
32+
ClockedSchedule = apps.get_model("django_celery_beat", "ClockedSchedule")
33+
34+
# Identify Talos PythonModule instances first
35+
module_qs = PythonModule.objects.filter(
36+
module="talos.Talos",
37+
base_path="api_app.analyzers_manager.observable_analyzers",
38+
)
39+
40+
# Remove all analyzer configs referencing these modules
41+
AnalyzerConfig.objects.filter(python_module__in=module_qs).delete()
42+
43+
for module in module_qs:
44+
update_task_id = getattr(module, "update_task_id", None)
45+
if update_task_id is not None:
46+
try:
47+
task = PeriodicTask.objects.get(id=update_task_id)
48+
except PeriodicTask.DoesNotExist:
49+
task = None
50+
if task is not None:
51+
schedule_data = (
52+
("interval", IntervalSchedule, task.interval),
53+
("crontab", CrontabSchedule, task.crontab),
54+
("solar", SolarSchedule, task.solar),
55+
("clocked", ClockedSchedule, task.clocked),
56+
)
57+
task.delete()
58+
for field_name, schedule_model, schedule in schedule_data:
59+
_cleanup_schedule(
60+
schedule,
61+
field_name,
62+
PeriodicTask,
63+
PythonModule,
64+
is_crontab=(schedule_model is CrontabSchedule),
65+
)
66+
# Capture modules own schedule before deletion
67+
module_schedules = [
68+
getattr(module, attr, None)
69+
for attr in ("update_schedule", "health_check_schedule")
70+
]
71+
module.delete()
72+
# Clean up orphaned CrontabSchedules from the module
73+
for sched in module_schedules:
74+
_cleanup_schedule(sched, "crontab", PeriodicTask, PythonModule, is_crontab=True)
75+
76+
77+
class Migration(migrations.Migration):
78+
dependencies = [
79+
("analyzers_manager", "0179_add_local_db_models_tor_danmeuk"),
80+
]
81+
82+
operations = [
83+
migrations.RunPython(
84+
remove_talos_forward, reverse_code=migrations.RunPython.noop
85+
),
86+
]
Lines changed: 11 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,21 @@
11
# This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl
22
# See the file 'LICENSE' for copying permission.
33

4-
import logging
5-
import os
6-
7-
import requests
8-
from django.conf import settings
9-
10-
from api_app.analyzers_manager import classes
4+
"""
5+
Minimal stub kept so that historical data migration
6+
0002_0116_analyzer_config_talosreputation can still import the module
7+
path during full_clean(). The analyzer itself is removed; migration
8+
0180_remove_talos_reputation deletes the DB rows.
9+
"""
10+
11+
from api_app.analyzers_manager.classes import ObservableAnalyzer
1112
from api_app.analyzers_manager.exceptions import AnalyzerRunException
1213

13-
logger = logging.getLogger(__name__)
14-
15-
db_name = "talos_ip_blacklist.txt"
16-
database_location = f"{settings.MEDIA_ROOT}/{db_name}"
17-
1814

19-
class Talos(classes.ObservableAnalyzer):
15+
class Talos(ObservableAnalyzer):
2016
def run(self):
21-
result = {"found": False}
22-
if not os.path.isfile(database_location) and not self.update():
23-
raise AnalyzerRunException("Failed extraction of talos db")
24-
25-
if not os.path.exists(database_location):
26-
raise AnalyzerRunException(f"database location {database_location} does not exist")
27-
28-
with open(database_location, "r", encoding="utf-8") as f:
29-
db = f.read()
30-
31-
db_list = db.split("\n")
32-
if self.observable_name in db_list:
33-
result["found"] = True
34-
35-
return result
17+
raise AnalyzerRunException("TalosReputation has been deprecated and removed.")
3618

3719
@classmethod
38-
def update(cls) -> bool:
39-
try:
40-
logger.info("starting download of db from talos")
41-
url = "https://snort.org/downloads/ip-block-list"
42-
r = requests.get(url)
43-
r.raise_for_status()
44-
45-
with open(database_location, "w", encoding="utf-8") as f:
46-
f.write(r.content.decode())
47-
48-
if not os.path.exists(database_location):
49-
return False
50-
logger.info("ended download of db from talos")
51-
return True
52-
except Exception as e:
53-
logger.exception(e)
54-
20+
def update(cls):
5521
return False
56-
57-
def _do_create_data_model(self):
58-
return super()._do_create_data_model()
59-
60-
def _update_data_model(self, data_model):
61-
super()._update_data_model(data_model)
62-
found = self.report.report.get("found", False)
63-
if found:
64-
data_model.external_references.append(
65-
f"https://www.talosintelligence.com/reputation_center/lookup?search={self.report.job.analyzable.name}"
66-
)
67-
data_model.evaluation = self.EVALUATIONS.MALICIOUS.value
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl
2+
# See the file 'LICENSE' for copying permission.
3+
4+
5+
from django.db import migrations
6+
7+
8+
def remove_talos_from_playbooks(apps, schema_editor):
9+
PlaybookConfig = apps.get_model("playbooks_manager", "PlaybookConfig")
10+
AnalyzerConfig = apps.get_model("analyzers_manager", "AnalyzerConfig")
11+
12+
try:
13+
talos_analyzer = AnalyzerConfig.objects.get(name="TalosReputation")
14+
except AnalyzerConfig.DoesNotExist:
15+
talos_analyzer = None
16+
17+
if talos_analyzer is not None:
18+
for playbook in PlaybookConfig.objects.filter(analyzers=talos_analyzer):
19+
playbook.analyzers.remove(talos_analyzer)
20+
21+
# Also scrub runtime_configuration if present
22+
for playbook in PlaybookConfig.objects.all():
23+
rc = playbook.runtime_configuration
24+
if isinstance(rc, dict) and "analyzers" in rc and "TalosReputation" in rc["analyzers"]:
25+
del rc["analyzers"]["TalosReputation"]
26+
playbook.runtime_configuration = rc
27+
playbook.save(update_fields=["runtime_configuration"])
28+
29+
30+
class Migration(migrations.Migration):
31+
dependencies = [
32+
("playbooks_manager", "0066_link_crawl_visualizer_to_playbook"),
33+
("analyzers_manager", "0179_add_local_db_models_tor_danmeuk"),
34+
]
35+
36+
operations = [
37+
migrations.RunPython(
38+
remove_talos_from_playbooks, reverse_code=migrations.RunPython.noop
39+
),
40+
]

api_app/visualizers_manager/visualizers/ip_reputation_services.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -329,20 +329,6 @@ def _tor(self):
329329
)
330330
return tor_report
331331

332-
@visualizable_error_handler_with_params("Talos Reputation")
333-
def _talos(self):
334-
try:
335-
analyzer_report = self.get_analyzer_reports().get(config__name="TalosReputation")
336-
except AnalyzerReport.DoesNotExist:
337-
logger.warning("TalosReputation report does not exist")
338-
else:
339-
found = analyzer_report.report.get("found", False)
340-
talos_report = self.Bool(
341-
value="Talos Reputation",
342-
disable=not (analyzer_report.status == ReportStatus.SUCCESS and found),
343-
)
344-
return talos_report
345-
346332
def run(self) -> List[Dict]:
347333
first_level_elements = []
348334
second_level_elements = []
@@ -378,8 +364,6 @@ def run(self) -> List[Dict]:
378364

379365
third_level_elements.append(self._tor())
380366

381-
third_level_elements.append(self._talos())
382-
383367
page = self.Page(name="Reputation")
384368
page.add_level(
385369
self.Level(

docker/scripts/cron/update_repositories

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
0 1 * * 3 root python3 docker exec -ti $(docker ps | grep intelowl_celery_worker_default | awk '{print $1}') python3 manage.py update_analyzer MaxMindGeoIP
2-
5 */6 * * * root python3 docker exec -ti $(docker ps | grep intelowl_celery_worker_default | awk '{print $1}') python3 manage.py update_analyzer TalosReputation
32
5 */6 * * * root python3 docker exec -ti $(docker ps | grep intelowl_celery_worker_default | awk '{print $1}') python3 manage.py update_analyzer PhishingArmy
43
*/10 * * * * root python3 docker exec -ti $(docker ps | grep intelowl_celery_worker_default | awk '{print $1}') python3 manage.py update_analyzer TorProject
54
0 4 * * * root python3 docker exec -ti $(docker ps | grep intelowl_celery_worker_default | awk '{print $1}') python3 manage.py update_analyzer Yara

tests/api_app/analyzers_manager/unit_tests/observable_analyzers/test_talos.py

Lines changed: 0 additions & 25 deletions
This file was deleted.

tests/test_crons.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
ja4_db,
1515
maxmind,
1616
phishing_army,
17-
talos,
1817
tor,
1918
tor_nodes_danmeuk,
2019
tweetfeeds,
@@ -90,11 +89,6 @@ def test_maxmind_updater(self):
9089
for db in maxmind.Maxmind.get_db_names():
9190
self.assertTrue(os.path.exists(db))
9291

93-
@if_mock_connections(patch("requests.get", return_value=MockUpResponse({}, 200, text="91.192.100.61")))
94-
def test_talos_updater(self, mock_get=None):
95-
db_file_path = talos.Talos.update()
96-
self.assertTrue(os.path.exists(db_file_path))
97-
9892
@if_mock_connections(
9993
patch(
10094
"requests.get",

0 commit comments

Comments
 (0)