dogesec-commons 1.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. dogesec_commons/__init__.py +0 -0
  2. dogesec_commons/asgi.py +16 -0
  3. dogesec_commons/objects/__init__.py +1 -0
  4. dogesec_commons/objects/apps.py +10 -0
  5. dogesec_commons/objects/conf.py +8 -0
  6. dogesec_commons/objects/db_view_creator.py +164 -0
  7. dogesec_commons/objects/helpers.py +660 -0
  8. dogesec_commons/objects/views.py +427 -0
  9. dogesec_commons/settings.py +161 -0
  10. dogesec_commons/stixifier/__init__.py +0 -0
  11. dogesec_commons/stixifier/apps.py +5 -0
  12. dogesec_commons/stixifier/conf.py +1 -0
  13. dogesec_commons/stixifier/migrations/0001_initial.py +36 -0
  14. dogesec_commons/stixifier/migrations/0002_profile_ai_content_check_variable.py +18 -0
  15. dogesec_commons/stixifier/migrations/0003_rename_ai_content_check_variable_profile_ai_content_check_provider_and_more.py +23 -0
  16. dogesec_commons/stixifier/migrations/0004_profile_identity_id.py +18 -0
  17. dogesec_commons/stixifier/migrations/0005_profile_generate_pdf.py +18 -0
  18. dogesec_commons/stixifier/migrations/__init__.py +0 -0
  19. dogesec_commons/stixifier/models.py +57 -0
  20. dogesec_commons/stixifier/serializers.py +192 -0
  21. dogesec_commons/stixifier/stixifier.py +252 -0
  22. dogesec_commons/stixifier/summarizer.py +62 -0
  23. dogesec_commons/stixifier/views.py +193 -0
  24. dogesec_commons/urls.py +45 -0
  25. dogesec_commons/utils/__init__.py +3 -0
  26. dogesec_commons/utils/autoschema.py +88 -0
  27. dogesec_commons/utils/exceptions.py +28 -0
  28. dogesec_commons/utils/filters.py +66 -0
  29. dogesec_commons/utils/ordering.py +47 -0
  30. dogesec_commons/utils/pagination.py +81 -0
  31. dogesec_commons/utils/schemas.py +27 -0
  32. dogesec_commons/utils/serializers.py +47 -0
  33. dogesec_commons/wsgi.py +16 -0
  34. dogesec_commons-1.0.2.dist-info/METADATA +57 -0
  35. dogesec_commons-1.0.2.dist-info/RECORD +37 -0
  36. dogesec_commons-1.0.2.dist-info/WHEEL +4 -0
  37. dogesec_commons-1.0.2.dist-info/licenses/LICENSE +202 -0
File without changes
@@ -0,0 +1,16 @@
1
+ """
2
+ ASGI config for dogesec_commons project.
3
+
4
+ It exposes the ASGI callable as a module-level variable named ``application``.
5
+
6
+ For more information on this file, see
7
+ https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/
8
+ """
9
+
10
+ import os
11
+
12
+ from django.core.asgi import get_asgi_application
13
+
14
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dogesec_commons.settings')
15
+
16
+ application = get_asgi_application()
@@ -0,0 +1 @@
1
+ from . import apps as app
@@ -0,0 +1,10 @@
1
+ from django.apps import AppConfig
2
+
3
+ class ArangoObjectsViewApp(AppConfig):
4
+ name = 'dogesec_commons.objects'
5
+ label = 'dogesec_arango_objects_views'
6
+
7
+ def ready(self) -> None:
8
+ from .db_view_creator import startup_func
9
+ startup_func()
10
+ return super().ready()
@@ -0,0 +1,8 @@
1
+ from django.conf import settings
2
+
3
+ MAXIMUM_PAGE_SIZE = getattr(settings, 'MAXIMUM_PAGE_SIZE', 200)
4
+ DEFAULT_PAGE_SIZE = getattr(settings, 'DEFAULT_PAGE_SIZE', 50)
5
+
6
+ DB = settings.ARANGODB_DATABASE
7
+ DB_NAME = f"{DB}_database"
8
+ ARANGODB_DATABASE_VIEW = getattr(settings, "ARANGODB_DATABASE_VIEW", f"{DB}_view")
@@ -0,0 +1,164 @@
1
+ import logging
2
+
3
+ import arango
4
+ import arango.exceptions
5
+ from arango.database import StandardDatabase
6
+ from arango import ArangoClient
7
+
8
+ from dogesec_commons.objects import conf
9
+
10
+ logging.basicConfig(
11
+ level=logging.INFO,
12
+ format='[ARANGODB VIEW] %(levelname)s %(asctime)s %(message)s',
13
+ datefmt='%Y-%m-%d %H:%M:%S'
14
+ )
15
+
16
+ from django.conf import settings
17
+
18
+
19
+ SORT_FIELDS = [
20
+ "id",
21
+ "type",
22
+ "created",
23
+ "modified",
24
+ "name",
25
+ ]
26
+
27
+ FILTER_HIDDEN_FIELDS = [
28
+ "_stix2arango_note",
29
+ "_id",
30
+ "_from",
31
+ "_to",
32
+ "_is_ref",
33
+ "_arango_cti_processor_note",
34
+ "_arango_cve_processor_note",
35
+ ]
36
+
37
+ FILTER_FIELDS_VERTEX = [
38
+ "type",
39
+ "name",
40
+ "labels",
41
+ ]
42
+ FILTER_FIELDS_EDGE = [
43
+ "source_ref",
44
+ "target_ref",
45
+ "relationship_type",
46
+ ]
47
+ FILTER_SCO_FIELDS = ['value', 'path', 'subject', 'number', 'pid', 'string', 'key', 'iban_number', 'payload_bin', 'hash', 'display_name', 'protocols', 'name', 'body']
48
+ FILTER_FIELDS = list(set(FILTER_FIELDS_EDGE + FILTER_FIELDS_VERTEX))
49
+
50
+
51
+ def create_database(client: ArangoClient, sys_db: StandardDatabase, db_name):
52
+ logging.info(f"creating database {db_name}")
53
+ try:
54
+ sys_db.create_database(db_name)
55
+ except arango.exceptions.DatabaseCreateError as e:
56
+ logging.error(e)
57
+ return client.db(
58
+ name=db_name, username=settings.ARANGODB_USERNAME, password=settings.ARANGODB_PASSWORD, verify=True
59
+ )
60
+
61
+
62
+ def create_view(db: StandardDatabase, view_name, sort_fields=SORT_FIELDS, filter_fields=[SORT_FIELDS, FILTER_FIELDS_VERTEX, FILTER_FIELDS_EDGE, FILTER_HIDDEN_FIELDS, FILTER_SCO_FIELDS]):
63
+ logging.info(f"creating view {view_name} in {db.name}")
64
+ primary_sort = []
65
+ for field in sort_fields:
66
+ primary_sort.append(dict(field=field, direction="asc"))
67
+ primary_sort.append(dict(field=field, direction="desc"))
68
+
69
+ all_fields = [*filter_fields, sort_fields]
70
+
71
+ try:
72
+ logging.info("try updating view (%s) if exists", view_name)
73
+ return update_view(db, all_fields, view_name)
74
+ except BaseException as e:
75
+ logging.info(f"view update not possible: {e}")
76
+
77
+ try:
78
+ logging.info("create new view: %s", view_name)
79
+ return db.create_arangosearch_view(
80
+ view_name, {"primarySort": primary_sort, "storedValues": all_fields}
81
+ )
82
+ except arango.exceptions.ViewCreateError as e:
83
+ logging.error(e)
84
+ return db.view(view_name)
85
+
86
+
87
+ def get_link_properties(collection_name: str):
88
+ if collection_name.endswith("_vertex_collection"):
89
+ return {
90
+ "fields": {name: {} for name in FILTER_FIELDS_VERTEX},
91
+ }
92
+ elif collection_name.endswith("_edge_collection"):
93
+ return {
94
+ "fields": {name: {} for name in FILTER_FIELDS_EDGE},
95
+ }
96
+ else:
97
+ return None
98
+
99
+
100
+ def link_one_collection(db: StandardDatabase, view_name, collection_name):
101
+ logging.info(f"linking collection {collection_name} to {view_name}")
102
+ view = db.view(view_name)
103
+ link = {"includeAllFields": True}
104
+ if link and collection_name:
105
+ view["links"][collection_name] = link
106
+ db.update_arangosearch_view(view_name, view)
107
+ logging.info(f"linked collection {collection_name} to {view_name}")
108
+
109
+
110
+ def update_view(db: StandardDatabase, filter_fields, view_name) -> bool:
111
+ view = db.view(view_name)
112
+ view_fields = [sv['fields'] for sv in view['stored_values']]
113
+ def hash_fields(fields: list[list[str]]) -> set[str]:
114
+ hashes = set()
115
+ for ff in fields:
116
+ hash_val = 0
117
+ for f in set(ff):
118
+ hash_val += hash(f)
119
+ hashes.add(hash_val)
120
+ return hashes
121
+ view_hash = hash_fields(view_fields)
122
+ fields_hash = hash_fields(filter_fields)
123
+
124
+ if view_hash == fields_hash:
125
+ return view
126
+
127
+ logging.info("old hash does not match new hash, updating...")
128
+
129
+ view['storedValues'] = [{"fields": v} for v in filter_fields]
130
+ view["stored_values"] = filter_fields
131
+
132
+ new_view = db.update_arangosearch_view(view_name, view)
133
+
134
+ # should update but for some reason update not working, so recreate instead
135
+ new_view_hash = hash_fields([sv['fields'] for sv in new_view['stored_values']])
136
+ if new_view_hash != fields_hash:
137
+ db.delete_view(view_name, ignore_missing=True)
138
+ raise Exception("recreate because update is impossible")
139
+ return new_view
140
+
141
+ def link_all_collections(db: StandardDatabase, view: dict):
142
+ links = view.get("links", {})
143
+ view_name = view["name"]
144
+ for collection in db.collections():
145
+ collection_name = collection["name"]
146
+ if collection["system"]:
147
+ continue
148
+ links[collection_name] = {"includeAllFields": True}
149
+ if not links[collection_name]:
150
+ del links[collection]
151
+ continue
152
+ logging.info(f"linking collection {collection_name} to {view_name}")
153
+ db.update_arangosearch_view(view_name, view)
154
+ logging.info(f"linked {len(links)} collections to view")
155
+
156
+
157
+ def startup_func():
158
+ logging.info("setting up database")
159
+ client = ArangoClient(settings.ARANGODB_HOST_URL)
160
+ sys_db = client.db(username=settings.ARANGODB_USERNAME, password=settings.ARANGODB_PASSWORD)
161
+ db = create_database(client, sys_db, conf.DB_NAME)
162
+ view = create_view(db, conf.ARANGODB_DATABASE_VIEW)
163
+ link_all_collections(db, view)
164
+ logging.info("app ready")