django-log-formatter-asim 1.1.0a3__py3-none-any.whl → 1.1.0a4__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.
- django_log_formatter_asim/__init__.py +3 -15
- django_log_formatter_asim/ecs.py +16 -0
- django_log_formatter_asim/events/authentication.py +19 -18
- django_log_formatter_asim/events/common.py +11 -2
- django_log_formatter_asim/events/file_activity.py +16 -5
- {django_log_formatter_asim-1.1.0a3.dist-info → django_log_formatter_asim-1.1.0a4.dist-info}/METADATA +1 -1
- django_log_formatter_asim-1.1.0a4.dist-info/RECORD +10 -0
- django_log_formatter_asim-1.1.0a3.dist-info/RECORD +0 -9
- {django_log_formatter_asim-1.1.0a3.dist-info → django_log_formatter_asim-1.1.0a4.dist-info}/LICENSE +0 -0
- {django_log_formatter_asim-1.1.0a3.dist-info → django_log_formatter_asim-1.1.0a4.dist-info}/WHEEL +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import logging
|
|
3
|
-
import os
|
|
4
3
|
from datetime import datetime
|
|
5
4
|
from datetime import timezone
|
|
6
5
|
from importlib.metadata import distribution
|
|
@@ -9,6 +8,8 @@ import ddtrace
|
|
|
9
8
|
from ddtrace.trace import tracer
|
|
10
9
|
from django.conf import settings
|
|
11
10
|
|
|
11
|
+
from .ecs import _get_container_id
|
|
12
|
+
|
|
12
13
|
|
|
13
14
|
class ASIMRootFormatter:
|
|
14
15
|
def __init__(self, record):
|
|
@@ -29,19 +30,6 @@ class ASIMRootFormatter:
|
|
|
29
30
|
|
|
30
31
|
return copied_dict
|
|
31
32
|
|
|
32
|
-
def _get_container_id(self):
|
|
33
|
-
"""
|
|
34
|
-
The dockerId (container Id) is available via the metadata endpoint. However, it looks like it is embedded in the
|
|
35
|
-
metadata URL e.g.:
|
|
36
|
-
ECS_CONTAINER_METADATA_URI=http://169.254.170.2/v3/709d1c10779d47b2a84db9eef2ebd041-0265927825
|
|
37
|
-
See: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-metadata-endpoint-v4-response.html
|
|
38
|
-
"""
|
|
39
|
-
|
|
40
|
-
try:
|
|
41
|
-
return os.environ["ECS_CONTAINER_METADATA_URI"].split("/")[-1]
|
|
42
|
-
except (KeyError, IndexError):
|
|
43
|
-
return ""
|
|
44
|
-
|
|
45
33
|
def _get_first_64_bits_of(self, trace_id):
|
|
46
34
|
# See https://docs.datadoghq.com/tracing/other_telemetry/connect_logs_and_traces/python/#no-standard-library-logging
|
|
47
35
|
return str((1 << 64) - 1 & trace_id)
|
|
@@ -65,7 +53,7 @@ class ASIMRootFormatter:
|
|
|
65
53
|
event_dict["service"] = ddtrace.config.service or ""
|
|
66
54
|
event_dict["version"] = ddtrace.config.version or ""
|
|
67
55
|
|
|
68
|
-
event_dict["container_id"] =
|
|
56
|
+
event_dict["container_id"] = _get_container_id()
|
|
69
57
|
|
|
70
58
|
return event_dict
|
|
71
59
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def _get_container_id():
|
|
5
|
+
"""
|
|
6
|
+
The dockerId (container Id) is available via the metadata endpoint.
|
|
7
|
+
|
|
8
|
+
However, it looks like it is embedded in the metadata URL e.g.:
|
|
9
|
+
ECS_CONTAINER_METADATA_URI=http://169.254.170.2/v3/709d1c10779d47b2a84db9eef2ebd041-0265927825
|
|
10
|
+
See: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-metadata-endpoint-v4-response.html
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
return os.environ["ECS_CONTAINER_METADATA_URI"].split("/")[-1]
|
|
15
|
+
except (KeyError, IndexError):
|
|
16
|
+
return ""
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import datetime
|
|
2
2
|
import json
|
|
3
|
+
import os
|
|
3
4
|
from enum import Enum
|
|
4
5
|
from typing import Literal
|
|
5
6
|
from typing import Optional
|
|
@@ -7,6 +8,8 @@ from typing import TypedDict
|
|
|
7
8
|
|
|
8
9
|
from django.http import HttpRequest
|
|
9
10
|
|
|
11
|
+
from django_log_formatter_asim.ecs import _get_container_id
|
|
12
|
+
|
|
10
13
|
from .common import Client
|
|
11
14
|
from .common import Result
|
|
12
15
|
from .common import Server
|
|
@@ -51,12 +54,6 @@ class AuthenticationUser(TypedDict):
|
|
|
51
54
|
"""
|
|
52
55
|
username: Optional[str]
|
|
53
56
|
"""
|
|
54
|
-
Email address for the user if one exists.
|
|
55
|
-
|
|
56
|
-
Defaults to the logged in Django User.email if not provided.
|
|
57
|
-
"""
|
|
58
|
-
email: Optional[str]
|
|
59
|
-
"""
|
|
60
57
|
A unique identifier for this authentication session if one exists.
|
|
61
58
|
|
|
62
59
|
Defaults to the Django Sessions session key if not provided.
|
|
@@ -86,7 +83,7 @@ def log_authentication(
|
|
|
86
83
|
- Django Session middlewares Session Key
|
|
87
84
|
- Client IP address
|
|
88
85
|
- URL requested by the client
|
|
89
|
-
- Server
|
|
86
|
+
- Server domain name
|
|
90
87
|
:param event: What authentication action was attempted, either "Logon" or "Logoff"
|
|
91
88
|
:param result: What outcome did the action have, either "Success", "Failure", "Partial", "NA"
|
|
92
89
|
:param login_method: What authentication mechanism was being used, one of:
|
|
@@ -132,10 +129,19 @@ def log_authentication(
|
|
|
132
129
|
"EventSchemaVersion": "0.1.4",
|
|
133
130
|
}
|
|
134
131
|
|
|
135
|
-
if "
|
|
136
|
-
log["
|
|
132
|
+
if "domain_name" in server:
|
|
133
|
+
log["HttpHost"] = server["domain_name"]
|
|
137
134
|
elif "HTTP_HOST" in request.META:
|
|
138
|
-
log["
|
|
135
|
+
log["HttpHost"] = request.get_host()
|
|
136
|
+
|
|
137
|
+
if "service_name" in server:
|
|
138
|
+
log["TargetAppName"] = server["service_name"]
|
|
139
|
+
elif os.environ.get("COPILOT_APPLICATION_NAME") and os.environ.get("COPILOT_SERVICE_NAME"):
|
|
140
|
+
app_name = f"{os.environ['COPILOT_APPLICATION_NAME']}-{os.environ['COPILOT_SERVICE_NAME']}"
|
|
141
|
+
log["TargetAppName"] = app_name
|
|
142
|
+
|
|
143
|
+
if container_id := _get_container_id():
|
|
144
|
+
log["ContainerId"] = container_id
|
|
139
145
|
|
|
140
146
|
if "ip_address" in client:
|
|
141
147
|
log["SrcIpAddr"] = client["ip_address"]
|
|
@@ -148,23 +154,18 @@ def log_authentication(
|
|
|
148
154
|
log["TargetUrl"] = request.scheme + "://" + request.get_host() + request.get_full_path()
|
|
149
155
|
|
|
150
156
|
if "role" in user:
|
|
151
|
-
log["
|
|
157
|
+
log["TargetUserType"] = user["role"]
|
|
152
158
|
|
|
153
159
|
if "sessionId" in user:
|
|
154
|
-
log["
|
|
160
|
+
log["TargetSessionId"] = user["sessionId"]
|
|
155
161
|
elif request.session.session_key:
|
|
156
|
-
log["
|
|
162
|
+
log["TargetSessionId"] = request.session.session_key
|
|
157
163
|
|
|
158
164
|
if "username" in user:
|
|
159
165
|
log["TargetUsername"] = user["username"]
|
|
160
166
|
elif hasattr(request, "user") and request.user.username:
|
|
161
167
|
log["TargetUsername"] = request.user.username
|
|
162
168
|
|
|
163
|
-
if "email" in user:
|
|
164
|
-
log["ActorUsername"] = user["email"]
|
|
165
|
-
elif hasattr(request, "user") and hasattr(request.user, "email") and request.user.email:
|
|
166
|
-
log["ActorUsername"] = request.user.email
|
|
167
|
-
|
|
168
169
|
if result_details:
|
|
169
170
|
log["EventResultDetails"] = result_details
|
|
170
171
|
|
|
@@ -33,13 +33,22 @@ class Server(TypedDict):
|
|
|
33
33
|
"""Dictionary to represent properties of the HTTP Server."""
|
|
34
34
|
|
|
35
35
|
"""
|
|
36
|
-
|
|
36
|
+
The FQDN that this server is listening to HTTP requests on. For example:
|
|
37
|
+
web.trade.gov.uk
|
|
37
38
|
|
|
38
39
|
Defaults to the WSGI HTTP_HOST field if not provided.
|
|
39
40
|
"""
|
|
40
|
-
|
|
41
|
+
domain_name: Optional[str]
|
|
41
42
|
"""Internet Protocol Address of the server serving this request."""
|
|
42
43
|
ip_address: Optional[str]
|
|
44
|
+
"""
|
|
45
|
+
A unique (within DBT) identifier for the software running on the server.
|
|
46
|
+
For example: berry-auctions-frontend
|
|
47
|
+
|
|
48
|
+
Defaults to combining the environment variables COPILOT_APPLICATION_NAME and
|
|
49
|
+
COPILOT_SERVICE_NAME separated by a '-'.
|
|
50
|
+
"""
|
|
51
|
+
service_name: Optional[str]
|
|
43
52
|
|
|
44
53
|
|
|
45
54
|
def _default_severity(result: Result) -> Severity:
|
|
@@ -7,6 +7,8 @@ from typing import TypedDict
|
|
|
7
7
|
|
|
8
8
|
from django.http import HttpRequest
|
|
9
9
|
|
|
10
|
+
from django_log_formatter_asim.ecs import _get_container_id
|
|
11
|
+
|
|
10
12
|
from .common import Client
|
|
11
13
|
from .common import Result
|
|
12
14
|
from .common import Server
|
|
@@ -94,7 +96,7 @@ def log_file_activity(
|
|
|
94
96
|
- Django Authentication systems current username
|
|
95
97
|
- Client IP address
|
|
96
98
|
- URL requested by the client
|
|
97
|
-
- Server
|
|
99
|
+
- Server domain name
|
|
98
100
|
:param event: What File Event action was attempted, one of:
|
|
99
101
|
- FileAccessed
|
|
100
102
|
- FileCreated
|
|
@@ -167,10 +169,19 @@ def log_file_activity(
|
|
|
167
169
|
if "size" in file:
|
|
168
170
|
log["TargetFileSize"] = file["size"]
|
|
169
171
|
|
|
170
|
-
if "
|
|
171
|
-
log["
|
|
172
|
+
if "domain_name" in server:
|
|
173
|
+
log["HttpHost"] = server["domain_name"]
|
|
172
174
|
elif "HTTP_HOST" in request.META:
|
|
173
|
-
log["
|
|
175
|
+
log["HttpHost"] = request.get_host()
|
|
176
|
+
|
|
177
|
+
if "service_name" in server:
|
|
178
|
+
log["TargetAppName"] = server["service_name"]
|
|
179
|
+
elif os.environ.get("COPILOT_APPLICATION_NAME") and os.environ.get("COPILOT_SERVICE_NAME"):
|
|
180
|
+
app_name = f"{os.environ['COPILOT_APPLICATION_NAME']}-{os.environ['COPILOT_SERVICE_NAME']}"
|
|
181
|
+
log["TargetAppName"] = app_name
|
|
182
|
+
|
|
183
|
+
if container_id := _get_container_id():
|
|
184
|
+
log["ContainerId"] = container_id
|
|
174
185
|
|
|
175
186
|
if "ip_address" in client:
|
|
176
187
|
log["SrcIpAddr"] = client["ip_address"]
|
|
@@ -184,7 +195,7 @@ def log_file_activity(
|
|
|
184
195
|
|
|
185
196
|
if "username" in user:
|
|
186
197
|
log["TargetUsername"] = user["username"]
|
|
187
|
-
elif request.user.username:
|
|
198
|
+
elif hasattr(request, "user") and request.user.username:
|
|
188
199
|
log["TargetUsername"] = request.user.username
|
|
189
200
|
|
|
190
201
|
if result_details:
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
django_log_formatter_asim/__init__.py,sha256=ftbSWdejSnWK_MpT3RSfTgcs3E-661FM-e3ugnoiBqA,7133
|
|
2
|
+
django_log_formatter_asim/ecs.py,sha256=SSg3A5pfS5E-Hm7AXQnN1RrtXclgq07oSBxPCRn5gDg,536
|
|
3
|
+
django_log_formatter_asim/events/__init__.py,sha256=th8AEFNM-J5lNlO-d8Lk465jXqplE3IoTwj4DlscwYo,92
|
|
4
|
+
django_log_formatter_asim/events/authentication.py,sha256=IjGTPb8Ucky-NtHGFe2CLwER-57lnMYoemjswWJE8Jk,6985
|
|
5
|
+
django_log_formatter_asim/events/common.py,sha256=9LeiEn11FJowf2QiI5MLXlGIbY4MVRChABVcfchX8ko,1676
|
|
6
|
+
django_log_formatter_asim/events/file_activity.py,sha256=fSNXWCr0De6EZDfoz-JQgQMQce4Wf9Kn2XeUPHW7oI0,7471
|
|
7
|
+
django_log_formatter_asim-1.1.0a4.dist-info/LICENSE,sha256=dP79lN73--7LMApnankTGLqDbImXg8iYFqWgnExGkGk,1090
|
|
8
|
+
django_log_formatter_asim-1.1.0a4.dist-info/METADATA,sha256=ygNuO5M_cSJoctnfCzAI6J4N8miKlpbeaEliD3ubmxs,5581
|
|
9
|
+
django_log_formatter_asim-1.1.0a4.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
10
|
+
django_log_formatter_asim-1.1.0a4.dist-info/RECORD,,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
django_log_formatter_asim/__init__.py,sha256=LDQQch2GKY6LRj-KOME393FCiwjisQ49ATWBEqAP4ZA,7684
|
|
2
|
-
django_log_formatter_asim/events/__init__.py,sha256=th8AEFNM-J5lNlO-d8Lk465jXqplE3IoTwj4DlscwYo,92
|
|
3
|
-
django_log_formatter_asim/events/authentication.py,sha256=OxWztyvgaIXRZm-ake_OrxVXoH4NVMW1PaWZQi67UN8,6863
|
|
4
|
-
django_log_formatter_asim/events/common.py,sha256=YJ_t6nXShoMwgqgezUzi1f5qA-8J5DcBJWTqwbdZehs,1358
|
|
5
|
-
django_log_formatter_asim/events/file_activity.py,sha256=Re51ZOrcy1k62bORruPwCTdhuQqExbN_OtZ9UuCgDBE,6967
|
|
6
|
-
django_log_formatter_asim-1.1.0a3.dist-info/LICENSE,sha256=dP79lN73--7LMApnankTGLqDbImXg8iYFqWgnExGkGk,1090
|
|
7
|
-
django_log_formatter_asim-1.1.0a3.dist-info/METADATA,sha256=3ivJhQmrP7al1vvMKK-zQX2iBiLX56nek4sLCUR9E1A,5581
|
|
8
|
-
django_log_formatter_asim-1.1.0a3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
9
|
-
django_log_formatter_asim-1.1.0a3.dist-info/RECORD,,
|
{django_log_formatter_asim-1.1.0a3.dist-info → django_log_formatter_asim-1.1.0a4.dist-info}/LICENSE
RENAMED
|
File without changes
|
{django_log_formatter_asim-1.1.0a3.dist-info → django_log_formatter_asim-1.1.0a4.dist-info}/WHEEL
RENAMED
|
File without changes
|