-
-
Notifications
You must be signed in to change notification settings - Fork 529
Engine #2685
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Engine #2685
Changes from 18 commits
Commits
Show all changes
51 commits
Select commit
Hold shift + click to select a range
9b3ea29
engine
0ssigeno 47dbca7
More stuff
0ssigeno 0248f08
More engine
0ssigeno ebdda39
More engine
0ssigeno 9926348
Removed old code
0ssigeno bc2351b
Blake
0ssigeno 92e2507
Fixes
0ssigeno a170e55
Fixes
0ssigeno 4987106
Fixes
0ssigeno 4fe8326
Fixes
0ssigeno 5d8c47a
Fix
0ssigeno 66c3b96
Fix merge with dict
0ssigeno 88966c6
Fix
0ssigeno 295dc06
More tests
0ssigeno 96ec0a4
Added another engine
0ssigeno 7a0e260
Analyzable
0ssigeno b0080ea
Merge branch 'develop' into engine
0ssigeno bfdb7be
Blake
0ssigeno a9de79f
Fixes
0ssigeno 57a033c
Fixes
0ssigeno 140ca3b
Fixes
0ssigeno c135206
Added error
0ssigeno caad40e
Added delete
0ssigeno a504028
Fixes
0ssigeno 888fb1b
Fixes
0ssigeno 327aba5
Blake
0ssigeno 96b9ef1
Fix
0ssigeno 91d998e
More fixes
0ssigeno 35f6e31
Fixes
0ssigeno caecc17
Fixes
0ssigeno 0e9258c
update
0ssigeno f7d6d2a
Fixes
0ssigeno 650f0ab
Fixes
0ssigeno a447168
Fix typo
0ssigeno 4ec6970
More fixes
0ssigeno 1f6a274
Merge remote-tracking branch 'origin/develop' into engine
0ssigeno 3a67780
More fixes
0ssigeno e1b838f
Fixed files
0ssigeno e967ddf
Update deepsource
0ssigeno 30af478
Fixes
0ssigeno 2f1ea6b
Typo
0ssigeno 5ada941
Fixes
0ssigeno 1e7834f
Merge branch 'develop' into engine
0ssigeno 3cc15c8
Fixes
0ssigeno 0aa3b39
Fixes
0ssigeno d442a2d
Fixes
0ssigeno 0069872
Merge branch 'develop' into engine
0ssigeno 0b9e202
Blake
0ssigeno eed5fbb
Fix
0ssigeno 149e606
Fix
0ssigeno 14c791e
Typo
0ssigeno File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| from django.contrib import admin | ||
|
|
||
| from api_app.analyzables_manager.models import Analyzable | ||
|
|
||
|
|
||
| @admin.register(Analyzable) | ||
| class AnalyzableAdmin(admin.ModelAdmin): | ||
| list_display = ["pk", "name", "sha1", "sha256", "md5"] | ||
| search_fields = ["name", "sha1", "sha256", "md5"] | ||
| ordering = ["name"] | ||
| list_filter = ["discovery_date"] |
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| # Generated by Django 4.2.17 on 2025-01-22 08:59 | ||
|
|
||
| from django.db import migrations, models | ||
| from django.utils.timezone import now | ||
|
|
||
| import api_app.defaults | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
|
|
||
| initial = True | ||
|
|
||
| dependencies = [] | ||
|
|
||
| operations = [ | ||
| migrations.CreateModel( | ||
| name="Analyzable", | ||
| fields=[ | ||
| ( | ||
| "id", | ||
| models.BigAutoField( | ||
| auto_created=True, | ||
| primary_key=True, | ||
| serialize=False, | ||
| verbose_name="ID", | ||
| ), | ||
| ), | ||
| ("md5", models.CharField(max_length=255, unique=True, editable=False)), | ||
| ( | ||
| "sha256", | ||
| models.CharField(max_length=255, unique=True, editable=False), | ||
| ), | ||
| ("sha1", models.CharField(max_length=255, unique=True, editable=False)), | ||
| ("name", models.CharField(max_length=255)), | ||
| ( | ||
| "mimetype", | ||
| models.CharField( | ||
| blank=True, max_length=80, null=True, default=None | ||
| ), | ||
| ), | ||
| ( | ||
| "file", | ||
| models.FileField( | ||
| null=True, | ||
| default=None, | ||
| blank=True, | ||
| upload_to=api_app.defaults.file_directory_path, | ||
| ), | ||
| ), | ||
| ( | ||
| "classification", | ||
| models.CharField( | ||
| max_length=100, | ||
| choices=[ | ||
| ("ip", "Ip"), | ||
| ("url", "Url"), | ||
| ("domain", "Domain"), | ||
| ("hash", "Hash"), | ||
| ("generic", "Generic"), | ||
| ("file", "File"), | ||
| ], | ||
| ), | ||
| ), | ||
| ("discovery_date", models.DateTimeField(default=now)), | ||
| ], | ||
| options={ | ||
| "abstract": False, | ||
| }, | ||
| ), | ||
| ] |
55 changes: 55 additions & 0 deletions
55
api_app/analyzables_manager/migrations/0002_migrate_data.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| from django.db import migrations | ||
|
|
||
|
|
||
| def migrate(apps, schema_editor): | ||
| Job = apps.get_model("api_app", "Job") | ||
| Analyzable = apps.get_model("analyzables_manager", "Analyzable") | ||
| for job in Job.objects.all().order_by("received_request_time"): | ||
| if job.is_sample: | ||
| obj, created = Analyzable.objects.get_or_create( | ||
| md5=job.md5, | ||
| defaults={ | ||
| "file": job.file, | ||
| "mimetype": job.file_mimetype, | ||
| "name": job.file_name, | ||
| "md5": job.md5, | ||
| "classification": "sample", | ||
| "discovery_date": job.received_request_time, | ||
| }, | ||
| ) | ||
| if created: | ||
| p = job.file.path | ||
| try: | ||
| p.rename(p.parent / job.md5) | ||
| except Exception: | ||
| ... | ||
| else: | ||
| job.file.name = job.md5 | ||
| else: | ||
| obj, created = Analyzable.objects.get_or_create( | ||
| md5=job.md5, | ||
| defaults={ | ||
| "name": job.observable_name, | ||
| "md5": job.md5, | ||
| "classification": job.observable_classification, | ||
| "discovery_date": job.received_request_time, | ||
| }, | ||
| ) | ||
| if created: | ||
| obj.full_clean() | ||
| obj.save() | ||
| job.analyzable = obj | ||
| job.save() | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
|
|
||
| dependencies = [ | ||
| ("contenttypes", "0002_remove_content_type_name"), | ||
| ("api_app", "0067_add_analyzable"), | ||
| ("analyzables_manager", "0001_initial"), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.RunPython(migrate, migrations.RunPython.noop), | ||
| ] |
25 changes: 25 additions & 0 deletions
25
...analyzables_manager/migrations/0003_analyzable_analyzables_classif_adf7ca_idx_and_more.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| # Generated by Django 4.2.17 on 2025-01-23 14:38 | ||
|
|
||
| from django.db import migrations, models | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
|
|
||
| dependencies = [ | ||
| ("analyzables_manager", "0002_migrate_data"), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.AddIndex( | ||
| model_name="analyzable", | ||
| index=models.Index( | ||
| fields=["classification"], name="analyzables_classif_adf7ca_idx" | ||
| ), | ||
| ), | ||
| migrations.AddIndex( | ||
| model_name="analyzable", | ||
| index=models.Index( | ||
| fields=["mimetype"], name="analyzables_mimetyp_321d7d_idx" | ||
| ), | ||
| ), | ||
| ] |
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| from typing import Type, Union | ||
|
|
||
| from django.core.exceptions import ValidationError | ||
| from django.db import models | ||
| from django.utils.timezone import now | ||
|
|
||
| from api_app.analyzables_manager.queryset import AnalyzableQuerySet | ||
| from api_app.choices import Classification | ||
| from api_app.data_model_manager.models import ( | ||
| BaseDataModel, | ||
| DomainDataModel, | ||
| FileDataModel, | ||
| IPDataModel, | ||
| ) | ||
| from api_app.defaults import file_directory_path | ||
| from api_app.helpers import calculate_md5, calculate_sha1, calculate_sha256 | ||
|
|
||
|
|
||
| class Analyzable(models.Model): | ||
| name = models.CharField(max_length=255) | ||
| discovery_date = models.DateTimeField(default=now) | ||
| md5 = models.CharField(max_length=255, unique=True, editable=False) | ||
| sha256 = models.CharField(max_length=255, unique=True, editable=False) | ||
| sha1 = models.CharField(max_length=255, unique=True, editable=False) | ||
| classification = models.CharField(max_length=100, choices=Classification.choices) | ||
| mimetype = models.CharField(max_length=80, blank=True, null=True, default=None) | ||
| file = models.FileField( | ||
| upload_to=file_directory_path, null=True, blank=True, default=None | ||
| ) | ||
|
|
||
| objects = AnalyzableQuerySet.as_manager() | ||
|
|
||
| class Meta: | ||
| indexes = [ | ||
| models.Index(fields=["classification"]), | ||
| models.Index(fields=["mimetype"]), | ||
| ] | ||
|
|
||
| def __str__(self): | ||
| return self.name | ||
|
|
||
| @property | ||
| def analyzed_object(self): | ||
| return self.file if self.is_sample else self.name | ||
|
|
||
| @property | ||
| def is_sample(self) -> bool: | ||
| return self.classification == Classification.FILE.value | ||
|
|
||
| def get_data_model_class(self) -> Type[BaseDataModel]: | ||
| if self.classification == Classification.IP.value: | ||
| return IPDataModel | ||
| elif self.classification in [ | ||
| Classification.URL.value, | ||
| Classification.DOMAIN.value, | ||
| ]: | ||
| return DomainDataModel | ||
| elif self.classification in [ | ||
| Classification.HASH.value, | ||
| Classification.FILE.value, | ||
| ]: | ||
| return FileDataModel | ||
| else: | ||
| raise NotImplementedError() | ||
|
|
||
| def _set_hashes(self, value: Union[str, bytes]): | ||
| if isinstance(value, str): | ||
| value = value.encode("utf-8") | ||
| if not self.md5: | ||
| self.md5 = calculate_md5(value) | ||
| if not self.sha256: | ||
| self.sha256 = calculate_sha256(value) | ||
| if not self.sha1: | ||
| self.sha1 = calculate_sha1(value) | ||
|
|
||
| def clean(self): | ||
| if self.classification == Classification.FILE.value: | ||
| if not self.mimetype or not self.file: | ||
| raise ValidationError("Mimetype and file must be set for samples") | ||
| content = self.read() | ||
| else: | ||
| if self.mimetype or self.file: | ||
| raise ValidationError( | ||
| "Mimetype and file must not be set for observables" | ||
| ) | ||
| content = self.name | ||
| self._set_hashes(content) | ||
|
|
||
| def read(self) -> bytes: | ||
| if self.classification == Classification.FILE.value: | ||
| self.file.seek(0) | ||
| return self.file.read() | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| from django.db.models import QuerySet | ||
|
|
||
|
|
||
| class AnalyzableQuerySet(QuerySet): | ||
|
|
||
| def visible_for_user(self, user): | ||
| from api_app.models import Job | ||
|
|
||
| jobs = ( | ||
| Job.objects.visible_for_user(user) | ||
| .values("analyzable") | ||
| .distinct() | ||
| .values_list("pk", flat=True) | ||
| ) | ||
| return self.filter(pk__in=jobs) | ||
|
|
||
| def create(self, *args, **kwargs): | ||
| obj = self.model(**kwargs) | ||
| self._for_write = True | ||
| obj.full_clean() | ||
| obj.save(force_insert=True, using=self.db) | ||
| return obj |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| from rest_framework.serializers import ModelSerializer | ||
|
|
||
| from api_app.analyzables_manager.models import Analyzable | ||
| from api_app.serializers.job import JobRelatedField | ||
|
|
||
|
|
||
| class AnalyzableSerializer(ModelSerializer): | ||
| jobs = JobRelatedField(many=True, read_only=True) | ||
|
|
||
| class Meta: | ||
| model = Analyzable | ||
| fields = "__all__" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| from django.db import models | ||
| from django.dispatch import receiver | ||
|
|
||
| from api_app.analyzables_manager.models import Analyzable | ||
|
|
||
|
|
||
| @receiver(models.signals.pre_delete, sender=Analyzable) | ||
| def pre_delete_analyzable(sender, instance: Analyzable, **kwargs): | ||
| """ | ||
| Signal receiver for the pre_delete signal of the Analyzable model. | ||
| Deletes the associated file if it exists. | ||
|
|
||
| Args: | ||
| sender (Model): The model class sending the signal. | ||
| instance (Analyzable): The instance of the model being deleted. | ||
| **kwargs: Additional keyword arguments. | ||
| """ | ||
| if instance.file: | ||
| instance.file.delete() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl | ||
| # See the file 'LICENSE' for copying permission. | ||
|
|
||
| from django.urls import include, path | ||
| from rest_framework import routers | ||
|
|
||
| from api_app.analyzables_manager.views import AnalyzableViewSet | ||
|
|
||
| # Routers provide an easy way of automatically determining the URL conf. | ||
|
|
||
|
|
||
| router = routers.DefaultRouter(trailing_slash=False) | ||
| router.register(r"analyzable", AnalyzableViewSet, basename="analyzable") | ||
|
|
||
| urlpatterns = [ | ||
| # Viewsets | ||
| path(r"", include(router.urls)), | ||
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| from rest_framework import viewsets | ||
| from rest_framework.permissions import IsAuthenticated | ||
|
|
||
| from api_app.analyzables_manager.serializers import AnalyzableSerializer | ||
|
|
||
|
|
||
| class AnalyzableViewSet(viewsets.ReadOnlyModelViewSet): | ||
|
|
||
| serializer_class = AnalyzableSerializer | ||
| permission_classes = [IsAuthenticated] | ||
|
|
||
| def get_queryset(self): | ||
| user = self.request.user | ||
| return super().get_queryset().visible_for_user(user) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.