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
@@ -0,0 +1,427 @@
1
+ from dogesec_commons.objects import conf
2
+ from dogesec_commons.utils.schemas import DEFAULT_400_RESPONSE
3
+ from .helpers import (
4
+ OBJECT_TYPES,
5
+ ArangoDBHelper,
6
+ SCO_TYPES,
7
+ SDO_TYPES,
8
+ SMO_TYPES,
9
+ SRO_SORT_FIELDS,
10
+ SMO_SORT_FIELDS,
11
+ SCO_SORT_FIELDS,
12
+ SDO_SORT_FIELDS,
13
+ )
14
+ from drf_spectacular.utils import extend_schema_view, extend_schema, OpenApiParameter
15
+ from drf_spectacular.types import OpenApiTypes
16
+ from rest_framework import viewsets, exceptions, decorators
17
+ from rest_framework.response import Response
18
+
19
+ from django.conf import settings
20
+
21
+ import textwrap
22
+
23
+
24
+ class QueryParams:
25
+ value = OpenApiParameter(
26
+ "value",
27
+ description=textwrap.dedent(
28
+ """
29
+ Search by the `value` field field of the SCO. This is the IoC. So if you're looking to retrieve a IP address by address you would enter the IP address here. Similarly, if you're looking for a credit card you would enter the card number here.
30
+ Search is wildcard. For example, `1.1` will return SCOs with `value` fields; `1.1.1.1`, `2.1.1.2`, etc.
31
+ If `value` field is named differently for the Object (e.g. `hash`) it will still be searched because these have been aliased to the `value` in the database search).
32
+ """
33
+ ),
34
+ )
35
+ sco_types = OpenApiParameter(
36
+ "types",
37
+ many=True,
38
+ explode=False,
39
+ description=textwrap.dedent(
40
+ """
41
+ Filter the results by one or more STIX SCO Object types
42
+ """
43
+ ),
44
+ enum=SCO_TYPES,
45
+ )
46
+ post_id = OpenApiParameter(
47
+ "post_id",
48
+ description=textwrap.dedent(
49
+ """
50
+ Filter the results to only contain objects present in the specified Post ID. Get a Post ID using the Feeds endpoints.
51
+ """
52
+ ),
53
+ )
54
+ SCO_PARAMS = [
55
+ value,
56
+ sco_types,
57
+ post_id,
58
+ OpenApiParameter("sort", enum=SCO_SORT_FIELDS),
59
+ ]
60
+
61
+ name = OpenApiParameter(
62
+ "name",
63
+ description=textwrap.dedent(
64
+ """
65
+ Allows results to be filtered on the `name` field of the SDO. Search is wildcard. For example, `Wanna` will return SDOs with the `name`; `WannaCry`, `WannaSmile`, etc.
66
+ """
67
+ ),
68
+ )
69
+ labels = OpenApiParameter(
70
+ "labels",
71
+ description=textwrap.dedent(
72
+ """
73
+ Allows results to be filtered on each value in the `labels` field of the SDO. Each value in the `labels` list will be searched individually.
74
+ Search is wildcard. For example, `needs` will return SDOs with `labels`; `need-attribution`, `needs-review`, etc. The value entered only needs to match one item in the `labels` list to return results.
75
+ """
76
+ ),
77
+ )
78
+ sdo_types = OpenApiParameter(
79
+ "types",
80
+ many=True,
81
+ explode=False,
82
+ description=textwrap.dedent(
83
+ """
84
+ Filter the results by one or more STIX Domain Object types
85
+ """
86
+ ),
87
+ enum=SDO_TYPES,
88
+ )
89
+
90
+ SDO_PARAMS = [
91
+ name,
92
+ labels,
93
+ sdo_types,
94
+ OpenApiParameter("sort", enum=SDO_SORT_FIELDS),
95
+ ]
96
+
97
+ source_ref = OpenApiParameter(
98
+ "source_ref",
99
+ description=textwrap.dedent(
100
+ """
101
+ Filter the results on the `source_ref` fields. The value entered should be a full ID of a STIX SDO or SCO which can be obtained from the respective Get Object endpoints. This endpoint allows for graph traversal use-cases as it returns STIX `relationship` objects that will tell you what objects are related to the one entered (in the `target_ref` property).
102
+ """
103
+ ),
104
+ )
105
+ source_ref_type = OpenApiParameter(
106
+ "source_ref_type",
107
+ many=True,
108
+ explode=False,
109
+ description=textwrap.dedent(
110
+ """
111
+ Filter the results by the STIX object type in the `source_ref` field. Unlike the `source_ref` filter that requires a full STIX object ID, this filter allows for a more open search. For example, `attack-pattern` will return all `relationship` Objects where the `source_ref` contains the ID of an `attack-pattern` Object.
112
+ """
113
+ ),
114
+ )
115
+ target_ref = OpenApiParameter(
116
+ "target_ref",
117
+ description=textwrap.dedent(
118
+ """
119
+ Filter the results on the `target_ref` fields. The value entered should be a full ID of a STIX SDO or SCO which can be obtained from the respective Get Object endpoints. This endpoint allows for graph traversal use-cases as it returns STIX `relationship` objects that will tell you what objects are related to the one entered (in the `source_ref` property).
120
+ """
121
+ ),
122
+ )
123
+ target_ref_type = OpenApiParameter(
124
+ "target_ref_type",
125
+ many=True,
126
+ explode=False,
127
+ description=textwrap.dedent(
128
+ """
129
+ Filter the results by the STIX object type in the `target_ref` field. Unlike the `target_ref` filter that requires a full STIX object ID, this filter allows for a more open search. For example, `attack-pattern` will return all `relationship` Objects where the `target_ref` contains the ID of an `attack-pattern` Object.
130
+ """
131
+ ),
132
+ )
133
+ relationship_type = OpenApiParameter(
134
+ "relationship_type",
135
+ description=textwrap.dedent(
136
+ """
137
+ Filter the results on the `relationship_type` field. Search is wildcard. For example, `in` will return `relationship` objects with ``relationship_type`s; `found-in`, `located-in`, etc.
138
+ """
139
+ ),
140
+ )
141
+ include_embedded_refs = OpenApiParameter(
142
+ "include_embedded_refs",
143
+ description=textwrap.dedent(
144
+ """
145
+ If `ignore_embedded_relationships` is set to `false` in the POST request to download data, stix2arango will create SROS for embedded relationships (e.g. from `created_by_refs`). You can choose to show them (`true`) or hide them (`false`) using this parameter. Default value if not passed is `true`.
146
+ """
147
+ ),
148
+ type=OpenApiTypes.BOOL,
149
+ )
150
+
151
+ SRO_PARAMS = [
152
+ source_ref,
153
+ source_ref_type,
154
+ target_ref,
155
+ target_ref_type,
156
+ relationship_type,
157
+ include_embedded_refs,
158
+ OpenApiParameter("sort", enum=SRO_SORT_FIELDS),
159
+ ]
160
+
161
+ all_types = OpenApiParameter(
162
+ "types",
163
+ many=True,
164
+ explode=False,
165
+ description=textwrap.dedent(
166
+ """
167
+ Filter the results by one or more STIX Object types
168
+ """
169
+ ),
170
+ enum=OBJECT_TYPES,
171
+ )
172
+ OBJECTS_PARAMS = [
173
+ all_types,
174
+ ]
175
+
176
+ smo_types = OpenApiParameter(
177
+ "types",
178
+ many=True,
179
+ explode=False,
180
+ description=textwrap.dedent(
181
+ """
182
+ Filter the results by one or more STIX Object types
183
+ """
184
+ ),
185
+ enum=SMO_TYPES,
186
+ )
187
+ SMO_PARAMS = [
188
+ smo_types,
189
+ OpenApiParameter("sort", enum=SMO_SORT_FIELDS),
190
+ ]
191
+
192
+ object_id_param = OpenApiParameter(
193
+ "object_id",
194
+ description="Filter by the STIX object ID. e.g. `ipv4-addr--ba6b3f21-d818-4e7c-bfff-765805177512`, `indicator--7bff059e-6963-4b50-b901-4aba20ce1c01`",
195
+ type=OpenApiTypes.STR,
196
+ location=OpenApiParameter.PATH,
197
+ )
198
+
199
+ visible_to = OpenApiParameter(
200
+ "visible_to",
201
+ description="Only show objects that are visible to the Identity `id` passed. e.g. passing `identity--b1ae1a15-6f4b-431e-b990-1b9678f35e15` would only show reports created by that identity (with any TLP level) or objects created by another identity ID but only if they are marked with `TLP:CLEAR` or `TLP:GREEN`.",
202
+ type=OpenApiTypes.STR,
203
+ )
204
+
205
+
206
+ @extend_schema_view(
207
+ retrieve=extend_schema(
208
+ summary="Get a STIX Object",
209
+ description=textwrap.dedent(
210
+ """
211
+ Get a STIX Object by its ID
212
+ """
213
+ ),
214
+ responses={200: ArangoDBHelper.STIX_OBJECT_SCHEMA, 404: DEFAULT_400_RESPONSE, 400: DEFAULT_400_RESPONSE},
215
+ parameters=[QueryParams.object_id_param],
216
+ ),
217
+ bundle=extend_schema(
218
+ summary="Get STIX Object's Bundle",
219
+ description=textwrap.dedent(
220
+ """
221
+ Return all objects the STIX Object has a relationship to as a bundle of all objects.
222
+ """
223
+ ),
224
+ responses=ArangoDBHelper.get_paginated_response_schema(),
225
+ parameters=ArangoDBHelper.get_schema_operation_parameters()
226
+ + [
227
+ QueryParams.object_id_param,
228
+ QueryParams.all_types,
229
+ QueryParams.include_embedded_refs,
230
+ QueryParams.visible_to,
231
+ ],
232
+ ),
233
+ )
234
+ class SingleObjectView(viewsets.ViewSet):
235
+ lookup_url_kwarg = "object_id"
236
+ openapi_tags = ["Objects"]
237
+ lookup_value_regex = (
238
+ r"[\w\-]+--[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
239
+ )
240
+
241
+ def retrieve(self, request, *args, **kwargs):
242
+ return ArangoDBHelper(conf.ARANGODB_DATABASE_VIEW, request).get_objects_by_id(
243
+ kwargs.get(self.lookup_url_kwarg)
244
+ )
245
+
246
+ @decorators.action(detail=True, methods=["GET"])
247
+ def bundle(self, request, *args, **kwargs):
248
+ return ArangoDBHelper(conf.ARANGODB_DATABASE_VIEW, request).get_object_bundle(
249
+ kwargs.get(self.lookup_url_kwarg)
250
+ )
251
+
252
+
253
+ @extend_schema_view(
254
+ reports=extend_schema(
255
+ responses=ArangoDBHelper.get_paginated_response_schema(
256
+ "reports",
257
+ {
258
+ "type": "object",
259
+ "properties": {
260
+ "type": {
261
+ "example": "report",
262
+ },
263
+ "id": {
264
+ "example": "report--a86627d4-285b-5358-b332-4e33f3ec1075",
265
+ },
266
+ },
267
+ "additionalProperties": True,
268
+ },
269
+ ),
270
+ parameters=ArangoDBHelper.get_schema_operation_parameters()
271
+ + [QueryParams.object_id_param],
272
+ summary="Get all Reports that contain this STIX Object",
273
+ description=textwrap.dedent(
274
+ """
275
+ Return all reports the STIX Object has a Relationship to.
276
+ """
277
+ ),
278
+ ),
279
+ destroy_in_report=extend_schema(
280
+ summary="Delete an Object from a Report",
281
+ description=textwrap.dedent(
282
+ """
283
+ Occasionally txt2stix will create an erroneous extraction from a text document. This endpoint allows you to remove the STIX objects created for such extractions.
284
+
285
+ This request will delete the object ID specified in the request, and ALL relationship objects that reference this Objects ID in either the `source_ref` or `target_ref` property of the relationship object.
286
+
287
+ You can safely to run this request on SCOs that are seen in multiple reports. Whilst Obstracts shows a single SCO with the same value with the same STIX ID (e.g. `1.1.1.1`), in the database multiple versions of the same SCO object exist, one for each report (identified using the field `_stix2arango=<REPORT_ID`). All objects created during the processing of this report have this field too.
288
+
289
+ **DANGER:** This action is irreversible. It also can create issues if not run carefully. For example, assume you have a connection from a report object as follows; Report -> Indicator -> IPv4. Should you delete the Indicator objects in this example, the IPv4 will no longer be directly connected to the report (though it will still appear in the report bundle, and the reports `object_refs` property).
290
+ """
291
+ ),
292
+ ),
293
+ )
294
+ class ObjectsWithReportsView(SingleObjectView):
295
+ @decorators.action(detail=True, methods=["GET"])
296
+ def reports(self, request, *args, **kwargs):
297
+ return ArangoDBHelper(
298
+ conf.ARANGODB_DATABASE_VIEW, request, "reports"
299
+ ).get_containing_reports(kwargs.get(self.lookup_url_kwarg))
300
+
301
+ @decorators.action(
302
+ detail=True,
303
+ methods=["DELETE"],
304
+ url_path=r"reports/(?P<report_id>report--[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})",
305
+ )
306
+ def destroy_in_report(
307
+ self, request, *args, object_id=None, report_id=None, **kwargs
308
+ ):
309
+ return ArangoDBHelper(
310
+ conf.ARANGODB_DATABASE_VIEW, request
311
+ ).delete_report_object(report_id=report_id, object_id=object_id)
312
+
313
+
314
+ @extend_schema_view(
315
+ list=extend_schema(
316
+ responses=ArangoDBHelper.get_paginated_response_schema(),
317
+ parameters=ArangoDBHelper.get_schema_operation_parameters()
318
+ + QueryParams.SDO_PARAMS + [QueryParams.visible_to],
319
+ summary="Search and filter STIX Domain Objects",
320
+ description=textwrap.dedent(
321
+ """
322
+ Search for domain objects (aka TTPs). If you have the object ID already, you can use the base GET Objects endpoint.
323
+ """
324
+ ),
325
+ ),
326
+ )
327
+ class SDOView(viewsets.ViewSet):
328
+ skip_list_view = True
329
+ openapi_tags = ["Objects"]
330
+
331
+ def list(self, request, *args, **kwargs):
332
+ return ArangoDBHelper(conf.ARANGODB_DATABASE_VIEW, request).get_sdos()
333
+
334
+
335
+ @extend_schema_view(
336
+ list=extend_schema(
337
+ responses=ArangoDBHelper.get_paginated_response_schema(),
338
+ parameters=ArangoDBHelper.get_schema_operation_parameters()
339
+ + QueryParams.SCO_PARAMS,
340
+ summary="Search and filter STIX Cyber Observable Objects",
341
+ description=textwrap.dedent(
342
+ """
343
+ Search for STIX Cyber Observable Objects (aka Indicators of Compromise). If you have the object ID already, you can use the base GET Objects endpoint.
344
+
345
+ Note the `value` filter searches the following object properties;
346
+
347
+ * `artifact.payload_bin`
348
+ * `autonomous-system.number`
349
+ * `bank-account.iban_number`
350
+ * `bank-card.number`
351
+ * `cryptocurrency-transaction.hash`
352
+ * `cryptocurrency-wallet.hash`
353
+ * `directory.path`
354
+ * `domain-name.value`
355
+ * `email-addr.value`
356
+ * `email-message.body`
357
+ * `file.name`
358
+ * `ipv4-addr.value`
359
+ * `ipv6-addr.value`
360
+ * `mac-addr.value`
361
+ * `mutex.value`
362
+ * `network-traffic.protocols`
363
+ * `phone-number.number`
364
+ * `process.pid`
365
+ * `software.name`
366
+ * `url.value`
367
+ * `user-account.display_name`
368
+ * `user-agent.string`
369
+ * `windows-registry-key.key`
370
+ * `x509-certificate.subject`
371
+ """
372
+ ),
373
+ ),
374
+ )
375
+ class SCOView(viewsets.ViewSet):
376
+ skip_list_view = True
377
+ openapi_tags = ["Objects"]
378
+
379
+ def list(self, request, *args, **kwargs):
380
+ matcher = {}
381
+ if post_id := request.query_params.dict().get("post_id"):
382
+ matcher["_obstracts_post_id"] = post_id
383
+ return ArangoDBHelper(conf.ARANGODB_DATABASE_VIEW, request).get_scos(
384
+ matcher=matcher
385
+ )
386
+
387
+
388
+ @extend_schema_view(
389
+ list=extend_schema(
390
+ responses=ArangoDBHelper.get_paginated_response_schema(),
391
+ parameters=ArangoDBHelper.get_schema_operation_parameters()
392
+ + QueryParams.SMO_PARAMS,
393
+ summary="Search and filter STIX Meta Objects",
394
+ description=textwrap.dedent(
395
+ """
396
+ Search for meta objects. If you have the object ID already, you can use the base GET Objects endpoint.
397
+ """
398
+ ),
399
+ )
400
+ )
401
+ class SMOView(viewsets.ViewSet):
402
+ skip_list_view = True
403
+ openapi_tags = ["Objects"]
404
+
405
+ def list(self, request, *args, **kwargs):
406
+ return ArangoDBHelper(conf.ARANGODB_DATABASE_VIEW, request).get_smos()
407
+
408
+
409
+ @extend_schema_view(
410
+ list=extend_schema(
411
+ responses=ArangoDBHelper.get_paginated_response_schema(),
412
+ parameters=ArangoDBHelper.get_schema_operation_parameters()
413
+ + QueryParams.SRO_PARAMS + [QueryParams.visible_to],
414
+ summary="Search and filter STIX Relationship Objects",
415
+ description=textwrap.dedent(
416
+ """
417
+ Search for relationship objects. This endpoint is particularly useful to search what Objects an SCO or SDO is linked to.
418
+ """
419
+ ),
420
+ ),
421
+ )
422
+ class SROView(viewsets.ViewSet):
423
+ skip_list_view = True
424
+ openapi_tags = ["Objects"]
425
+
426
+ def list(self, request, *args, **kwargs):
427
+ return ArangoDBHelper(conf.ARANGODB_DATABASE_VIEW, request).get_sros()
@@ -0,0 +1,161 @@
1
+ """
2
+ Django settings for dogesec_commons project.
3
+
4
+ Generated by 'django-admin startproject' using Django 5.1.5.
5
+
6
+ For more information on this file, see
7
+ https://docs.djangoproject.com/en/5.1/topics/settings/
8
+
9
+ For the full list of settings and their values, see
10
+ https://docs.djangoproject.com/en/5.1/ref/settings/
11
+ """
12
+
13
+ import os
14
+ from pathlib import Path
15
+
16
+ # Build paths inside the project like this: BASE_DIR / 'subdir'.
17
+ BASE_DIR = Path(__file__).resolve().parent.parent
18
+
19
+
20
+ # Quick-start development settings - unsuitable for production
21
+ # See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
22
+
23
+ # SECURITY WARNING: keep the secret key used in production secret!
24
+ SECRET_KEY = 'django-insecure-umqh5d5yygalt#x%ekanq_liz6c17fts)w!p=i4d$2ll%t2kro'
25
+
26
+ # SECURITY WARNING: don't run with debug turned on in production!
27
+ DEBUG = True
28
+
29
+ ALLOWED_HOSTS = []
30
+
31
+
32
+ # Application definition
33
+
34
+ INSTALLED_APPS = [
35
+ 'django.contrib.admin',
36
+ 'django.contrib.auth',
37
+ 'django.contrib.contenttypes',
38
+ 'django.contrib.sessions',
39
+ 'django.contrib.messages',
40
+ 'django.contrib.staticfiles',
41
+ 'dogesec_commons.stixifier',
42
+ 'dogesec_commons.objects',
43
+ 'drf_spectacular',
44
+ ]
45
+
46
+ MIDDLEWARE = [
47
+ 'django.middleware.security.SecurityMiddleware',
48
+ 'django.contrib.sessions.middleware.SessionMiddleware',
49
+ 'django.middleware.common.CommonMiddleware',
50
+ 'django.middleware.csrf.CsrfViewMiddleware',
51
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
52
+ 'django.contrib.messages.middleware.MessageMiddleware',
53
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
54
+ ]
55
+
56
+ ROOT_URLCONF = 'dogesec_commons.urls'
57
+
58
+ TEMPLATES = [
59
+ {
60
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
61
+ 'DIRS': [],
62
+ 'APP_DIRS': True,
63
+ 'OPTIONS': {
64
+ 'context_processors': [
65
+ 'django.template.context_processors.debug',
66
+ 'django.template.context_processors.request',
67
+ 'django.contrib.auth.context_processors.auth',
68
+ 'django.contrib.messages.context_processors.messages',
69
+ ],
70
+ },
71
+ },
72
+ ]
73
+
74
+ WSGI_APPLICATION = 'dogesec_commons.wsgi.application'
75
+
76
+
77
+ # Database
78
+ # https://docs.djangoproject.com/en/5.1/ref/settings/#databases
79
+
80
+
81
+ DATABASES = {
82
+
83
+ 'default': {
84
+ 'ENGINE': 'django.db.backends.postgresql',
85
+ 'NAME': os.getenv('POSTGRES_DB'), # Database name
86
+ 'USER': os.getenv('POSTGRES_USER'), # Database user
87
+ 'PASSWORD': os.getenv('POSTGRES_PASSWORD'), # Database password
88
+ 'HOST': os.getenv('POSTGRES_HOST'), # PostgreSQL service name in Docker Compose
89
+ 'PORT': os.getenv('POSTGRES_PORT', '5432'), # PostgreSQL default port
90
+ },
91
+
92
+ }
93
+
94
+
95
+ # Password validation
96
+ # https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators
97
+
98
+ AUTH_PASSWORD_VALIDATORS = [
99
+ {
100
+ 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
101
+ },
102
+ {
103
+ 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
104
+ },
105
+ {
106
+ 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
107
+ },
108
+ {
109
+ 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
110
+ },
111
+ ]
112
+
113
+
114
+ # Internationalization
115
+ # https://docs.djangoproject.com/en/5.1/topics/i18n/
116
+
117
+ LANGUAGE_CODE = 'en-us'
118
+
119
+ TIME_ZONE = 'UTC'
120
+
121
+ USE_I18N = True
122
+
123
+ USE_TZ = True
124
+
125
+
126
+ # Static files (CSS, JavaScript, Images)
127
+ # https://docs.djangoproject.com/en/5.1/howto/static-files/
128
+
129
+ STATIC_URL = 'static/'
130
+
131
+ # Default primary key field type
132
+ # https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field
133
+
134
+ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
135
+
136
+ MAXIMUM_PAGE_SIZE = int(os.getenv("MAX_PAGE_SIZE", 50))
137
+ DEFAULT_PAGE_SIZE = int(os.getenv("DEFAULT_PAGE_SIZE", 50))
138
+
139
+
140
+ SPECTACULAR_SETTINGS = {
141
+ # available SwaggerUI configuration parameters
142
+ # https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/
143
+ "SWAGGER_UI_SETTINGS": {
144
+ "deepLinking": True,
145
+ "persistAuthorization": True,
146
+ "displayOperationId": True,
147
+ },
148
+ # available SwaggerUI versions: https://github.com/swagger-api/swagger-ui/releases
149
+ "SWAGGER_UI_DIST": "https://cdn.jsdelivr.net/npm/swagger-ui-dist@latest", # default
150
+ }
151
+
152
+ REST_FRAMEWORK = {
153
+ # YOUR SETTINGS
154
+ 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
155
+ 'EXCEPTION_HANDLER': "dogesec_commons.utils.custom_exception_handler",
156
+ }
157
+
158
+ ARANGODB_DATABASE = os.getenv('ARANGODB_DATABASE')
159
+ ARANGODB_USERNAME = os.getenv('ARANGODB_USERNAME')
160
+ ARANGODB_PASSWORD = os.getenv('ARANGODB_PASSWORD')
161
+ ARANGODB_HOST_URL = os.getenv("ARANGODB_HOST_URL")
File without changes
@@ -0,0 +1,5 @@
1
+ from django.apps import AppConfig
2
+
3
+ class StixifierAppConfig(AppConfig):
4
+ name = 'dogesec_commons.stixifier'
5
+ label = 'dogesec_stixifier'
@@ -0,0 +1 @@
1
+ TXT2STIX_INCLUDE_URL = "https://github.com/muchdogesec/txt2stix/blob/main/includes/"
@@ -0,0 +1,36 @@
1
+ # Generated by Django 5.1.5 on 2025-02-18 11:00
2
+
3
+ import django.contrib.postgres.fields
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ initial = True
10
+
11
+ dependencies = [
12
+ ]
13
+
14
+ operations = [
15
+ migrations.CreateModel(
16
+ name='Profile',
17
+ fields=[
18
+ ('id', models.UUIDField(primary_key=True, serialize=False)),
19
+ ('created', models.DateTimeField(auto_now_add=True)),
20
+ ('name', models.CharField(max_length=250, unique=True)),
21
+ ('extractions', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=256), size=None)),
22
+ ('relationship_mode', models.CharField(choices=[('ai', 'AI Relationship'), ('standard', 'Standard Relationship')], default='standard', max_length=20)),
23
+ ('extract_text_from_image', models.BooleanField(default=False)),
24
+ ('defang', models.BooleanField()),
25
+ ('ai_settings_relationships', models.CharField(max_length=256, null=True)),
26
+ ('ai_settings_extractions', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=256), default=list, size=None)),
27
+ ('ai_summary_provider', models.CharField(max_length=256, null=True)),
28
+ ('ignore_image_refs', models.BooleanField(default=True)),
29
+ ('ignore_link_refs', models.BooleanField(default=True)),
30
+ ('ignore_extraction_boundary', models.BooleanField(default=False)),
31
+ ('ignore_embedded_relationships_sro', models.BooleanField(default=True)),
32
+ ('ignore_embedded_relationships_smo', models.BooleanField(default=True)),
33
+ ('ignore_embedded_relationships', models.BooleanField(default=False)),
34
+ ],
35
+ ),
36
+ ]
@@ -0,0 +1,18 @@
1
+ # Generated by Django 5.1.5 on 2025-02-19 15:34
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('dogesec_stixifier', '0001_initial'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name='profile',
15
+ name='ai_content_check_variable',
16
+ field=models.CharField(default=None, max_length=256, null=True),
17
+ ),
18
+ ]
@@ -0,0 +1,23 @@
1
+ # Generated by Django 5.1.5 on 2025-02-20 11:15
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('dogesec_stixifier', '0002_profile_ai_content_check_variable'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.RenameField(
14
+ model_name='profile',
15
+ old_name='ai_content_check_variable',
16
+ new_name='ai_content_check_provider',
17
+ ),
18
+ migrations.AddField(
19
+ model_name='profile',
20
+ name='ai_create_attack_flow',
21
+ field=models.BooleanField(default=True),
22
+ ),
23
+ ]