django-log-formatter-asim 1.1.0a4__py3-none-any.whl → 1.2.0a0__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/events/authentication.py +41 -14
- django_log_formatter_asim/events/common.py +2 -2
- django_log_formatter_asim/events/file_activity.py +82 -41
- {django_log_formatter_asim-1.1.0a4.dist-info → django_log_formatter_asim-1.2.0a0.dist-info}/METADATA +70 -11
- django_log_formatter_asim-1.2.0a0.dist-info/RECORD +10 -0
- django_log_formatter_asim-1.1.0a4.dist-info/RECORD +0 -10
- {django_log_formatter_asim-1.1.0a4.dist-info → django_log_formatter_asim-1.2.0a0.dist-info}/LICENSE +0 -0
- {django_log_formatter_asim-1.1.0a4.dist-info → django_log_formatter_asim-1.2.0a0.dist-info}/WHEEL +0 -0
|
@@ -2,6 +2,7 @@ import datetime
|
|
|
2
2
|
import json
|
|
3
3
|
import os
|
|
4
4
|
from enum import Enum
|
|
5
|
+
from hashlib import sha3_512
|
|
5
6
|
from typing import Literal
|
|
6
7
|
from typing import Optional
|
|
7
8
|
from typing import TypedDict
|
|
@@ -30,7 +31,7 @@ class AuthenticationLoginMethod(str, Enum):
|
|
|
30
31
|
ExternalIDP = "External IdP"
|
|
31
32
|
|
|
32
33
|
|
|
33
|
-
class AuthenticationUser(TypedDict):
|
|
34
|
+
class AuthenticationUser(TypedDict, total=False):
|
|
34
35
|
"""Dictionary to represent properties of the users session."""
|
|
35
36
|
|
|
36
37
|
"""What type of role best describes this Authentication event."""
|
|
@@ -109,17 +110,37 @@ def log_authentication(
|
|
|
109
110
|
|
|
110
111
|
See also: https://learn.microsoft.com/en-us/azure/sentinel/normalization-schema-authentication
|
|
111
112
|
"""
|
|
112
|
-
if user == None:
|
|
113
|
-
user = {}
|
|
114
|
-
if server == None:
|
|
115
|
-
server = {}
|
|
116
|
-
if client == None:
|
|
117
|
-
client = {}
|
|
118
|
-
|
|
119
|
-
event_created = time_generated or datetime.datetime.now(tz=datetime.timezone.utc)
|
|
120
113
|
|
|
114
|
+
_log_authentication(
|
|
115
|
+
request,
|
|
116
|
+
event,
|
|
117
|
+
result,
|
|
118
|
+
login_method,
|
|
119
|
+
user={} if user == None else user,
|
|
120
|
+
server={} if server == None else server,
|
|
121
|
+
client={} if client == None else client,
|
|
122
|
+
event_created=time_generated or datetime.datetime.now(tz=datetime.timezone.utc),
|
|
123
|
+
severity=severity,
|
|
124
|
+
result_details=result_details,
|
|
125
|
+
message=message,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _log_authentication(
|
|
130
|
+
request: HttpRequest,
|
|
131
|
+
event: AuthenticationEvent,
|
|
132
|
+
result: Result,
|
|
133
|
+
login_method: AuthenticationLoginMethod,
|
|
134
|
+
user: AuthenticationUser,
|
|
135
|
+
server: Server,
|
|
136
|
+
client: Client,
|
|
137
|
+
event_created: datetime.datetime,
|
|
138
|
+
severity: Optional[Severity] = None,
|
|
139
|
+
result_details: Optional[str] = None,
|
|
140
|
+
message: Optional[str] = None,
|
|
141
|
+
):
|
|
121
142
|
log = {
|
|
122
|
-
"
|
|
143
|
+
"EventStartTime": event_created.isoformat(),
|
|
123
144
|
"EventSeverity": severity or _default_severity(result),
|
|
124
145
|
"EventOriginalType": _event_code(event, result),
|
|
125
146
|
"EventType": event,
|
|
@@ -141,7 +162,7 @@ def log_authentication(
|
|
|
141
162
|
log["TargetAppName"] = app_name
|
|
142
163
|
|
|
143
164
|
if container_id := _get_container_id():
|
|
144
|
-
log["
|
|
165
|
+
log["TargetContainerId"] = container_id
|
|
145
166
|
|
|
146
167
|
if "ip_address" in client:
|
|
147
168
|
log["SrcIpAddr"] = client["ip_address"]
|
|
@@ -157,9 +178,9 @@ def log_authentication(
|
|
|
157
178
|
log["TargetUserType"] = user["role"]
|
|
158
179
|
|
|
159
180
|
if "sessionId" in user:
|
|
160
|
-
log["TargetSessionId"] = user["sessionId"]
|
|
161
|
-
elif request.session.session_key:
|
|
162
|
-
log["TargetSessionId"] = request.session.session_key
|
|
181
|
+
log["TargetSessionId"] = _cryptographically_hash(user["sessionId"])
|
|
182
|
+
elif hasattr(request, "session") and request.session.session_key:
|
|
183
|
+
log["TargetSessionId"] = _cryptographically_hash(request.session.session_key)
|
|
163
184
|
|
|
164
185
|
if "username" in user:
|
|
165
186
|
log["TargetUsername"] = user["username"]
|
|
@@ -184,6 +205,12 @@ log_authentication.LoginMethod = AuthenticationLoginMethod
|
|
|
184
205
|
log_authentication.Severity = Severity
|
|
185
206
|
|
|
186
207
|
|
|
208
|
+
def _cryptographically_hash(data: Optional[str]) -> Optional[str]:
|
|
209
|
+
if data is None:
|
|
210
|
+
return None
|
|
211
|
+
return sha3_512(data.encode("UTF-8")).hexdigest()
|
|
212
|
+
|
|
213
|
+
|
|
187
214
|
def _event_code(event: AuthenticationEvent, result: Result) -> str:
|
|
188
215
|
if event == AuthenticationEvent.Logon:
|
|
189
216
|
if result == Result.Success:
|
|
@@ -19,7 +19,7 @@ class Severity(str, Enum):
|
|
|
19
19
|
High = "High"
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
class Client(TypedDict):
|
|
22
|
+
class Client(TypedDict, total=False):
|
|
23
23
|
"""Dictionary to represent properties of the HTTP Client."""
|
|
24
24
|
|
|
25
25
|
"""Internet Protocol Address of the client making the Authentication
|
|
@@ -29,7 +29,7 @@ class Client(TypedDict):
|
|
|
29
29
|
requested_url: Optional[str]
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
class Server(TypedDict):
|
|
32
|
+
class Server(TypedDict, total=False):
|
|
33
33
|
"""Dictionary to represent properties of the HTTP Server."""
|
|
34
34
|
|
|
35
35
|
"""
|
|
@@ -31,24 +31,30 @@ class FileActivityEvent(str, Enum):
|
|
|
31
31
|
FolderModified = "FolderModified"
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
class
|
|
35
|
-
"""
|
|
34
|
+
class FileActivityFileBase(TypedDict):
|
|
35
|
+
"""Mandatory field definitions of FileActivityFile."""
|
|
36
36
|
|
|
37
37
|
"""
|
|
38
|
-
The full, normalized path of the target file, including the folder or
|
|
39
|
-
the file name, and the extension.
|
|
38
|
+
The full, normalized path of the target file, including the folder or
|
|
39
|
+
location, the file name, and the extension.
|
|
40
40
|
"""
|
|
41
41
|
path: str
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class FileActivityFile(FileActivityFileBase, total=False):
|
|
45
|
+
"""Dictionary to represent properties of either the target or source
|
|
46
|
+
file."""
|
|
47
|
+
|
|
42
48
|
"""
|
|
43
49
|
The name of the target file, without a path or a location, but with an
|
|
44
50
|
extension if available. This field should be similar to the final element in
|
|
45
|
-
the
|
|
51
|
+
the *FilePath field.
|
|
46
52
|
|
|
47
53
|
Defaults to extracting the name based off the path if not provided.
|
|
48
54
|
"""
|
|
49
55
|
name: Optional[str]
|
|
50
56
|
"""
|
|
51
|
-
The
|
|
57
|
+
The file extension.
|
|
52
58
|
|
|
53
59
|
Defaults to extracting the extension based off the path if not provided.
|
|
54
60
|
"""
|
|
@@ -59,13 +65,13 @@ class FileActivityFile(TypedDict):
|
|
|
59
65
|
Allowed values are listed in the IANA Media Types repository.
|
|
60
66
|
"""
|
|
61
67
|
content_type: Optional[str]
|
|
62
|
-
"""The SHA256 value of the
|
|
68
|
+
"""The SHA256 value of the file."""
|
|
63
69
|
sha256: Optional[str]
|
|
64
|
-
"""The size of the
|
|
70
|
+
"""The size of the file in bytes."""
|
|
65
71
|
size: Optional[int]
|
|
66
72
|
|
|
67
73
|
|
|
68
|
-
class FileActivityUser(TypedDict):
|
|
74
|
+
class FileActivityUser(TypedDict, total=False):
|
|
69
75
|
"""
|
|
70
76
|
A unique identifier for the user.
|
|
71
77
|
|
|
@@ -80,6 +86,7 @@ def log_file_activity(
|
|
|
80
86
|
event: FileActivityEvent,
|
|
81
87
|
result: Result,
|
|
82
88
|
file: FileActivityFile,
|
|
89
|
+
source_file: Optional[FileActivityFile] = None,
|
|
83
90
|
user: Optional[FileActivityUser] = None,
|
|
84
91
|
server: Optional[Server] = None,
|
|
85
92
|
client: Optional[Client] = None,
|
|
@@ -111,7 +118,10 @@ def log_file_activity(
|
|
|
111
118
|
- FolderModified
|
|
112
119
|
:param result: What outcome did the action have, either "Success", "Failure", "Partial", "NA"
|
|
113
120
|
:param file: Dictionary containing information on the target of this File event see
|
|
114
|
-
|
|
121
|
+
FileActivityFile for more details.
|
|
122
|
+
:param source_file: Dictionary containing information on the source of this File event,
|
|
123
|
+
this MUST be used for a FileRenamed, FileMoved, FileCopied, FolderMoved
|
|
124
|
+
operation. See FileActivityFile for more details.
|
|
115
125
|
:param user: Dictionary containing information on the logged in users username.
|
|
116
126
|
:param server: Dictionary containing information on the server servicing this File event
|
|
117
127
|
see Server class for more details.
|
|
@@ -129,45 +139,49 @@ def log_file_activity(
|
|
|
129
139
|
|
|
130
140
|
See also: https://learn.microsoft.com/en-us/azure/sentinel/normalization-schema-file-event
|
|
131
141
|
"""
|
|
132
|
-
if user == None:
|
|
133
|
-
user = {}
|
|
134
|
-
if server == None:
|
|
135
|
-
server = {}
|
|
136
|
-
if client == None:
|
|
137
|
-
client = {}
|
|
138
|
-
|
|
139
|
-
event_created = time_generated or datetime.datetime.now(tz=datetime.timezone.utc)
|
|
140
142
|
|
|
143
|
+
_log_file_activity(
|
|
144
|
+
request,
|
|
145
|
+
event,
|
|
146
|
+
result,
|
|
147
|
+
file,
|
|
148
|
+
source_file,
|
|
149
|
+
user={} if user == None else user,
|
|
150
|
+
server={} if server == None else server,
|
|
151
|
+
client={} if client == None else client,
|
|
152
|
+
event_created=time_generated or datetime.datetime.now(tz=datetime.timezone.utc),
|
|
153
|
+
severity=severity,
|
|
154
|
+
result_details=result_details,
|
|
155
|
+
message=message,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def _log_file_activity(
|
|
160
|
+
request: HttpRequest,
|
|
161
|
+
event: FileActivityEvent,
|
|
162
|
+
result: Result,
|
|
163
|
+
file: FileActivityFile,
|
|
164
|
+
source_file: Optional[FileActivityFile],
|
|
165
|
+
user: FileActivityUser,
|
|
166
|
+
server: Server,
|
|
167
|
+
client: Client,
|
|
168
|
+
event_created: datetime.datetime,
|
|
169
|
+
severity: Optional[Severity] = None,
|
|
170
|
+
result_details: Optional[str] = None,
|
|
171
|
+
message: Optional[str] = None,
|
|
172
|
+
):
|
|
141
173
|
log = {
|
|
142
174
|
"EventSchema": "FileEvent",
|
|
143
175
|
"EventSchemaVersion": "0.2.1",
|
|
144
176
|
"EventType": event,
|
|
145
177
|
"EventResult": result,
|
|
146
|
-
"
|
|
178
|
+
"EventStartTime": event_created.isoformat(),
|
|
147
179
|
"EventSeverity": severity or _default_severity(result),
|
|
148
|
-
"TargetFilePath": file["path"],
|
|
149
180
|
}
|
|
150
181
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
log["TargetFileName"] = os.path.basename(file["path"])
|
|
155
|
-
|
|
156
|
-
if "extension" in file:
|
|
157
|
-
log["TargetFileExtension"] = file["extension"]
|
|
158
|
-
else:
|
|
159
|
-
file_name_parts = list(filter(None, log["TargetFileName"].split(".", 1)))
|
|
160
|
-
if len(file_name_parts) > 1:
|
|
161
|
-
log["TargetFileExtension"] = file_name_parts[1]
|
|
162
|
-
|
|
163
|
-
if "content_type" in file:
|
|
164
|
-
log["TargetFileMimeType"] = file["content_type"]
|
|
165
|
-
|
|
166
|
-
if "sha256" in file:
|
|
167
|
-
log["TargetFileSHA256"] = file["sha256"]
|
|
168
|
-
|
|
169
|
-
if "size" in file:
|
|
170
|
-
log["TargetFileSize"] = file["size"]
|
|
182
|
+
log.update(_generate_file_attributes(file, "Target"))
|
|
183
|
+
if source_file:
|
|
184
|
+
log.update(_generate_file_attributes(source_file, "Src"))
|
|
171
185
|
|
|
172
186
|
if "domain_name" in server:
|
|
173
187
|
log["HttpHost"] = server["domain_name"]
|
|
@@ -181,7 +195,7 @@ def log_file_activity(
|
|
|
181
195
|
log["TargetAppName"] = app_name
|
|
182
196
|
|
|
183
197
|
if container_id := _get_container_id():
|
|
184
|
-
log["
|
|
198
|
+
log["TargetContainerId"] = container_id
|
|
185
199
|
|
|
186
200
|
if "ip_address" in client:
|
|
187
201
|
log["SrcIpAddr"] = client["ip_address"]
|
|
@@ -210,6 +224,33 @@ def log_file_activity(
|
|
|
210
224
|
print(json.dumps(log), flush=True)
|
|
211
225
|
|
|
212
226
|
|
|
227
|
+
def _generate_file_attributes(file: FileActivityFile, prefix: str) -> dict:
|
|
228
|
+
log = {prefix + "FilePath": file["path"]}
|
|
229
|
+
|
|
230
|
+
if "name" in file:
|
|
231
|
+
log[prefix + "FileName"] = file["name"]
|
|
232
|
+
else:
|
|
233
|
+
log[prefix + "FileName"] = os.path.basename(file["path"])
|
|
234
|
+
|
|
235
|
+
if "extension" in file:
|
|
236
|
+
log[prefix + "FileExtension"] = file["extension"]
|
|
237
|
+
else:
|
|
238
|
+
file_name_parts = list(filter(None, log[prefix + "FileName"].split(".", 1)))
|
|
239
|
+
if len(file_name_parts) > 1:
|
|
240
|
+
log[prefix + "FileExtension"] = file_name_parts[1]
|
|
241
|
+
|
|
242
|
+
if "content_type" in file:
|
|
243
|
+
log[prefix + "FileMimeType"] = file["content_type"]
|
|
244
|
+
|
|
245
|
+
if "sha256" in file:
|
|
246
|
+
log[prefix + "FileSHA256"] = file["sha256"]
|
|
247
|
+
|
|
248
|
+
if "size" in file:
|
|
249
|
+
log[prefix + "FileSize"] = file["size"]
|
|
250
|
+
|
|
251
|
+
return log
|
|
252
|
+
|
|
253
|
+
|
|
213
254
|
log_file_activity.Event = FileActivityEvent
|
|
214
255
|
log_file_activity.Result = Result
|
|
215
256
|
log_file_activity.Severity = Severity
|
{django_log_formatter_asim-1.1.0a4.dist-info → django_log_formatter_asim-1.2.0a0.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: django-log-formatter-asim
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0a0
|
|
4
4
|
Summary: Formats Django logs in ASIM format.
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Department for Business and Trade Platform Team
|
|
@@ -25,8 +25,6 @@ The library formats Django logs in [ASIM format](https://learn.microsoft.com/en-
|
|
|
25
25
|
|
|
26
26
|
Mapping to the format may not be complete, but best effort has been made to create logical field mappings.
|
|
27
27
|
|
|
28
|
-
If you need to amend the mapping, you can implement a custom formatter.
|
|
29
|
-
|
|
30
28
|
## Installation
|
|
31
29
|
|
|
32
30
|
``` shell
|
|
@@ -35,7 +33,16 @@ pip install django-log-formatter-asim
|
|
|
35
33
|
|
|
36
34
|
## Usage
|
|
37
35
|
|
|
38
|
-
|
|
36
|
+
This package provides the following ASIM functionality:
|
|
37
|
+
|
|
38
|
+
- A Python [logging.Formatter] implementation.
|
|
39
|
+
- A module of functions `django_log_formatter_asim.events` which generate ASIM event log entries.
|
|
40
|
+
|
|
41
|
+
[logging.Formatter]: https://docs.python.org/3/library/logging.html#formatter-objects
|
|
42
|
+
|
|
43
|
+
### `logging.Formatter` setup
|
|
44
|
+
|
|
45
|
+
Using the formatter in a Django logging configuration:
|
|
39
46
|
|
|
40
47
|
``` python
|
|
41
48
|
from django_log_formatter_asim import ASIMFormatter
|
|
@@ -66,15 +73,61 @@ LOGGING = {
|
|
|
66
73
|
},
|
|
67
74
|
}
|
|
68
75
|
```
|
|
69
|
-
In this example we assign the ASIM formatter to a `handler` and ensure both `root` and `django` loggers use this `handler`. We then set `propagate` to `False` on the `django` logger, to avoid duplicating logs at the root level.
|
|
70
76
|
|
|
71
|
-
|
|
77
|
+
In this example we assign the ASIM formatter to a `handler` and ensure both `root` and `django` loggers use this `handler`.
|
|
78
|
+
We then set `propagate` to `False` on the `django` logger, to avoid duplicating logs at the root level.
|
|
72
79
|
|
|
73
|
-
|
|
80
|
+
### ASIM Events
|
|
74
81
|
|
|
75
|
-
|
|
82
|
+
The events mostly follow the Microsoft schema but have been tailored to Department of Business and Trade needs.
|
|
83
|
+
|
|
84
|
+
Events are designed for simple integrate into your Django app.
|
|
85
|
+
Each will take additional information from the [Django HttpRequest object][django-request].
|
|
86
|
+
|
|
87
|
+
[django-request]: https://docs.djangoproject.com/en/5.2/ref/request-response/#httprequest-objects
|
|
88
|
+
|
|
89
|
+
#### Authentication event
|
|
76
90
|
|
|
77
|
-
|
|
91
|
+
Following the [ASIM Authentication Schema](https://learn.microsoft.com/en-us/azure/sentinel/normalization-schema-authentication).
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
# Example usage
|
|
95
|
+
from django_log_formatter_asim.events import log_authentication
|
|
96
|
+
|
|
97
|
+
log_authentication(
|
|
98
|
+
request,
|
|
99
|
+
event=log_authentication.Event.Logoff,
|
|
100
|
+
result=log_authentication.Result.Success,
|
|
101
|
+
login_method=log_authentication.LoginMethod.UsernamePassword,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# Example JSON printed to standard output
|
|
105
|
+
{
|
|
106
|
+
# Values provided as arguments
|
|
107
|
+
"EventType": "Logoff",
|
|
108
|
+
"EventResult": "Success",
|
|
109
|
+
"LogonMethod": "Username & Password",
|
|
110
|
+
|
|
111
|
+
# Calculated / Hard coded fields
|
|
112
|
+
"EventStartTime": "2025-07-02T08:15:20+00:00",
|
|
113
|
+
"EventSeverity": "Informational",
|
|
114
|
+
"EventOriginalType": "001c",
|
|
115
|
+
"EventSchema": "Authentication",
|
|
116
|
+
"EventSchemaVersion": "0.1.4",
|
|
117
|
+
|
|
118
|
+
# Taken from Django HttpRequest object
|
|
119
|
+
"HttpHost": "WebServer.local",
|
|
120
|
+
"SrcIpAddr": "192.168.1.101",
|
|
121
|
+
"TargetUrl": "https://WebServer.local/steel",
|
|
122
|
+
"TargetSessionId": "def456",
|
|
123
|
+
"TargetUsername": "Adrian"
|
|
124
|
+
|
|
125
|
+
# Taken from DBT Platform environment variables
|
|
126
|
+
"TargetAppName": "export-analytics-frontend",
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Settings
|
|
78
131
|
|
|
79
132
|
`DLFA_LOG_PERSONALLY_IDENTIFIABLE_INFORMATION` - the formatter checks this setting to see if personally identifiable information should be logged. If this is not set to true, only the user's id is logged.
|
|
80
133
|
|
|
@@ -89,7 +142,7 @@ if is_copilot():
|
|
|
89
142
|
DLFA_TRACE_HEADERS = ("X-B3-TraceId", "X-B3-SpanId")
|
|
90
143
|
```
|
|
91
144
|
|
|
92
|
-
|
|
145
|
+
### Formatter classes
|
|
93
146
|
|
|
94
147
|
``` python
|
|
95
148
|
ASIM_FORMATTERS = {
|
|
@@ -104,7 +157,7 @@ The default class for other loggers is:
|
|
|
104
157
|
ASIMSystemFormatter
|
|
105
158
|
```
|
|
106
159
|
|
|
107
|
-
|
|
160
|
+
### Creating a custom `logging.Formatter`
|
|
108
161
|
|
|
109
162
|
If you wish to create your own ASIM formatter, you can inherit from ASIMSystemFormatter and call _get_event_base to get the base level logging data for use in augmentation:
|
|
110
163
|
|
|
@@ -118,6 +171,12 @@ If you wish to create your own ASIM formatter, you can inherit from ASIMSystemFo
|
|
|
118
171
|
return logger_event
|
|
119
172
|
```
|
|
120
173
|
|
|
174
|
+
## Dependencies
|
|
175
|
+
|
|
176
|
+
This package uses [Django IPware](https://github.com/un33k/django-ipware) for IP address capture.
|
|
177
|
+
|
|
178
|
+
This package is compatible with [Django User Agents](https://pypi.org/project/django-user-agents) which, when used, will enhance logged user agent information.
|
|
179
|
+
|
|
121
180
|
## Contributing to the `django-log-formatter-asim` package
|
|
122
181
|
|
|
123
182
|
### Getting started
|
|
@@ -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=WUHSllqTKTLnEdRlLn2SqCn3YR1_AKPA3y8Gm22CyIY,7808
|
|
5
|
+
django_log_formatter_asim/events/common.py,sha256=-QjR9QPkMDqD3nXPiukAJvm8qjUt2LwzhL_zN5ae_t0,1702
|
|
6
|
+
django_log_formatter_asim/events/file_activity.py,sha256=h8xlY0ABDCejAVnRMJ0aeWdNJZpu_54et1squMEfSM8,8755
|
|
7
|
+
django_log_formatter_asim-1.2.0a0.dist-info/LICENSE,sha256=dP79lN73--7LMApnankTGLqDbImXg8iYFqWgnExGkGk,1090
|
|
8
|
+
django_log_formatter_asim-1.2.0a0.dist-info/METADATA,sha256=ofAaVdlWggllH93apSQg16S0ZHaPmF1xd27APovOirc,7428
|
|
9
|
+
django_log_formatter_asim-1.2.0a0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
10
|
+
django_log_formatter_asim-1.2.0a0.dist-info/RECORD,,
|
|
@@ -1,10 +0,0 @@
|
|
|
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,,
|
{django_log_formatter_asim-1.1.0a4.dist-info → django_log_formatter_asim-1.2.0a0.dist-info}/LICENSE
RENAMED
|
File without changes
|
{django_log_formatter_asim-1.1.0a4.dist-info → django_log_formatter_asim-1.2.0a0.dist-info}/WHEEL
RENAMED
|
File without changes
|