django-log-formatter-asim 1.1.0a2__tar.gz → 1.1.0a4__tar.gz
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-1.1.0a2 → django_log_formatter_asim-1.1.0a4}/PKG-INFO +1 -1
- {django_log_formatter_asim-1.1.0a2 → django_log_formatter_asim-1.1.0a4}/django_log_formatter_asim/__init__.py +3 -15
- django_log_formatter_asim-1.1.0a4/django_log_formatter_asim/ecs.py +16 -0
- {django_log_formatter_asim-1.1.0a2 → django_log_formatter_asim-1.1.0a4}/django_log_formatter_asim/events/authentication.py +24 -12
- {django_log_formatter_asim-1.1.0a2 → django_log_formatter_asim-1.1.0a4}/django_log_formatter_asim/events/common.py +12 -3
- {django_log_formatter_asim-1.1.0a2 → django_log_formatter_asim-1.1.0a4}/django_log_formatter_asim/events/file_activity.py +20 -9
- {django_log_formatter_asim-1.1.0a2 → django_log_formatter_asim-1.1.0a4}/pyproject.toml +1 -1
- {django_log_formatter_asim-1.1.0a2 → django_log_formatter_asim-1.1.0a4}/LICENSE +0 -0
- {django_log_formatter_asim-1.1.0a2 → django_log_formatter_asim-1.1.0a4}/README.md +0 -0
- {django_log_formatter_asim-1.1.0a2 → django_log_formatter_asim-1.1.0a4}/django_log_formatter_asim/events/__init__.py +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
|
|
@@ -80,7 +83,7 @@ def log_authentication(
|
|
|
80
83
|
- Django Session middlewares Session Key
|
|
81
84
|
- Client IP address
|
|
82
85
|
- URL requested by the client
|
|
83
|
-
- Server
|
|
86
|
+
- Server domain name
|
|
84
87
|
:param event: What authentication action was attempted, either "Logon" or "Logoff"
|
|
85
88
|
:param result: What outcome did the action have, either "Success", "Failure", "Partial", "NA"
|
|
86
89
|
:param login_method: What authentication mechanism was being used, one of:
|
|
@@ -126,10 +129,19 @@ def log_authentication(
|
|
|
126
129
|
"EventSchemaVersion": "0.1.4",
|
|
127
130
|
}
|
|
128
131
|
|
|
129
|
-
if "
|
|
130
|
-
log["
|
|
131
|
-
elif "
|
|
132
|
-
log["
|
|
132
|
+
if "domain_name" in server:
|
|
133
|
+
log["HttpHost"] = server["domain_name"]
|
|
134
|
+
elif "HTTP_HOST" in request.META:
|
|
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
|
|
133
145
|
|
|
134
146
|
if "ip_address" in client:
|
|
135
147
|
log["SrcIpAddr"] = client["ip_address"]
|
|
@@ -138,21 +150,21 @@ def log_authentication(
|
|
|
138
150
|
|
|
139
151
|
if "requested_url" in client:
|
|
140
152
|
log["TargetUrl"] = client["requested_url"]
|
|
141
|
-
elif "
|
|
153
|
+
elif "HTTP_HOST" in request.META:
|
|
142
154
|
log["TargetUrl"] = request.scheme + "://" + request.get_host() + request.get_full_path()
|
|
143
155
|
|
|
144
156
|
if "role" in user:
|
|
145
|
-
log["
|
|
157
|
+
log["TargetUserType"] = user["role"]
|
|
146
158
|
|
|
147
159
|
if "sessionId" in user:
|
|
148
|
-
log["
|
|
160
|
+
log["TargetSessionId"] = user["sessionId"]
|
|
149
161
|
elif request.session.session_key:
|
|
150
|
-
log["
|
|
162
|
+
log["TargetSessionId"] = request.session.session_key
|
|
151
163
|
|
|
152
164
|
if "username" in user:
|
|
153
|
-
log["
|
|
154
|
-
elif request.user.username:
|
|
155
|
-
log["
|
|
165
|
+
log["TargetUsername"] = user["username"]
|
|
166
|
+
elif hasattr(request, "user") and request.user.username:
|
|
167
|
+
log["TargetUsername"] = request.user.username
|
|
156
168
|
|
|
157
169
|
if result_details:
|
|
158
170
|
log["EventResultDetails"] = result_details
|
|
@@ -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
|
-
Defaults to the WSGI
|
|
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
|
-
elif "
|
|
173
|
-
log["
|
|
172
|
+
if "domain_name" in server:
|
|
173
|
+
log["HttpHost"] = server["domain_name"]
|
|
174
|
+
elif "HTTP_HOST" in request.META:
|
|
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"]
|
|
@@ -179,13 +190,13 @@ def log_file_activity(
|
|
|
179
190
|
|
|
180
191
|
if "requested_url" in client:
|
|
181
192
|
log["TargetUrl"] = client["requested_url"]
|
|
182
|
-
elif "
|
|
193
|
+
elif "HTTP_HOST" in request.META:
|
|
183
194
|
log["TargetUrl"] = request.scheme + "://" + request.get_host() + request.get_full_path()
|
|
184
195
|
|
|
185
196
|
if "username" in user:
|
|
186
|
-
log["
|
|
187
|
-
elif request.user.username:
|
|
188
|
-
log["
|
|
197
|
+
log["TargetUsername"] = user["username"]
|
|
198
|
+
elif hasattr(request, "user") and request.user.username:
|
|
199
|
+
log["TargetUsername"] = request.user.username
|
|
189
200
|
|
|
190
201
|
if result_details:
|
|
191
202
|
log["EventResultDetails"] = result_details
|
|
@@ -3,7 +3,7 @@ line-length = 100
|
|
|
3
3
|
|
|
4
4
|
[tool.poetry]
|
|
5
5
|
name = "django-log-formatter-asim"
|
|
6
|
-
version = "1.1.
|
|
6
|
+
version = "1.1.0a4"
|
|
7
7
|
description = "Formats Django logs in ASIM format."
|
|
8
8
|
authors = ["Department for Business and Trade Platform Team <sre-team@digital.trade.gov.uk>"]
|
|
9
9
|
license = "MIT"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|