dn-scribe commited on
Commit
985b46f
·
1 Parent(s): 9cd1061

Fix syslog from use + filtering

Browse files
Files changed (4) hide show
  1. api/syslog.py +36 -40
  2. app.py +2 -0
  3. templates/logs.html +47 -8
  4. web/events.py +43 -0
api/syslog.py CHANGED
@@ -20,50 +20,46 @@ def receive_syslog():
20
  return jsonify({'error': 'JSON data required'}), 400
21
 
22
  # Extract log messages from JSON
23
- messages = data.get('messages', [])
24
- if not messages:
25
- # Single message
26
- messages = [data.get('message', '')]
27
 
28
  processed_count = 0
29
 
30
- for message in messages:
31
- if not message:
32
- continue
33
 
34
- try:
35
- # Parse RFC 5424 message
36
- parsed = parse_rfc5424_log(message)
37
-
38
- # Create log entry
39
- log_entry = SystemLog(
40
- facility=parsed['facility'],
41
- severity=parsed['severity'],
42
- version=parsed['version'],
43
- timestamp=parsed['timestamp'],
44
- hostname=parsed['hostname'],
45
- app_name=parsed['app_name'],
46
- proc_id=parsed['proc_id'],
47
- msg_id=parsed['msg_id'],
48
- structured_data=parsed['structured_data'],
49
- message=parsed['message'],
50
- user_id=get_current_user_safe().id if get_current_user_safe() else None,
51
- source_ip=request.remote_addr,
52
- event_type='syslog_received'
53
- )
54
-
55
- db.session.add(log_entry)
56
- processed_count += 1
57
-
58
- except Exception as e:
59
- # Log parsing error but continue processing
60
- log_event(
61
- severity=4,
62
- message=f"Failed to parse syslog message: {str(e)}",
63
- event_type="syslog_parse_error",
64
- user_id=get_current_user_safe().id if get_current_user_safe() else None
65
- )
66
-
67
  db.session.commit()
68
 
69
  return jsonify({
 
20
  return jsonify({'error': 'JSON data required'}), 400
21
 
22
  # Extract log messages from JSON
23
+ message = data.get('syslog_message', [])
24
+ if not message:
25
+ return jsonify({'error': 'syslog_message field required'}), 400
 
26
 
27
  processed_count = 0
28
 
 
 
 
29
 
30
+ try:
31
+ # Parse RFC 5424 message
32
+ parsed = parse_rfc5424_log(message)
33
+
34
+ # Create log entry
35
+ log_entry = SystemLog(
36
+ facility=parsed['facility'],
37
+ severity=parsed['severity'],
38
+ version=parsed['version'],
39
+ timestamp=parsed['timestamp'],
40
+ hostname=parsed['hostname'],
41
+ app_name=parsed['app_name'],
42
+ proc_id=parsed['proc_id'],
43
+ msg_id=parsed['msg_id'],
44
+ structured_data=parsed['structured_data'],
45
+ message=parsed['message'],
46
+ user_id=get_current_user_safe().id if get_current_user_safe() else None,
47
+ source_ip=request.remote_addr,
48
+ event_type='syslog_received'
49
+ )
50
+
51
+ db.session.add(log_entry)
52
+ processed_count += 1
53
+
54
+ except Exception as e:
55
+ # Log parsing error but continue processing
56
+ log_event(
57
+ severity=4,
58
+ message=f"Failed to parse syslog message: {str(e)}",
59
+ event_type="syslog_parse_error",
60
+ user_id=get_current_user_safe().id if get_current_user_safe() else None
61
+ )
62
+
63
  db.session.commit()
64
 
65
  return jsonify({
app.py CHANGED
@@ -55,9 +55,11 @@ with app.app_context():
55
  from api.syslog import syslog_bp
56
  from web.routes import web_bp
57
  from api.webhooks import webhooks_bp
 
58
 
59
  app.register_blueprint(evidence_bp, url_prefix='/')
60
  app.register_blueprint(login_bp, url_prefix='/v1')
61
  app.register_blueprint(syslog_bp, url_prefix='/')
62
  app.register_blueprint(webhooks_bp, url_prefix='/api')
63
  app.register_blueprint(web_bp)
 
 
55
  from api.syslog import syslog_bp
56
  from web.routes import web_bp
57
  from api.webhooks import webhooks_bp
58
+ from web.events import events_bp
59
 
60
  app.register_blueprint(evidence_bp, url_prefix='/')
61
  app.register_blueprint(login_bp, url_prefix='/v1')
62
  app.register_blueprint(syslog_bp, url_prefix='/')
63
  app.register_blueprint(webhooks_bp, url_prefix='/api')
64
  app.register_blueprint(web_bp)
65
+ app.register_blueprint(events_bp)
templates/logs.html CHANGED
@@ -48,13 +48,7 @@
48
  <label for="eventTypeFilter" class="form-label">Event Type</label>
49
  <select class="form-select" id="eventTypeFilter" name="event_type">
50
  <option value="">All Events</option>
51
- <option value="login_success" {{ 'selected' if event_type_filter == 'login_success' }}>Login Success</option>
52
- <option value="login_failed" {{ 'selected' if event_type_filter == 'login_failed' }}>Login Failed</option>
53
- <option value="upload_started" {{ 'selected' if event_type_filter == 'upload_started' }}>Upload Started</option>
54
- <option value="upload_completed" {{ 'selected' if event_type_filter == 'upload_completed' }}>Upload Completed</option>
55
- <option value="attestation_created" {{ 'selected' if event_type_filter == 'attestation_created' }}>Attestation Created</option>
56
- <option value="download_url_generated" {{ 'selected' if event_type_filter == 'download_url_generated' }}>Download URL Generated</option>
57
- <option value="syslog_received" {{ 'selected' if event_type_filter == 'syslog_received' }}>Syslog Received</option>
58
  </select>
59
  </div>
60
  <div class="col-md-4">
@@ -221,6 +215,7 @@ const severityLevels = {
221
  };
222
 
223
  document.addEventListener('DOMContentLoaded', function() {
 
224
  loadLogs();
225
  loadLogStats();
226
 
@@ -237,6 +232,47 @@ document.addEventListener('DOMContentLoaded', function() {
237
  });
238
  });
239
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
240
  async function loadLogs(page = 1) {
241
  try {
242
  const params = new URLSearchParams({
@@ -467,7 +503,10 @@ function applyFilters() {
467
  }
468
 
469
  function refreshLogs() {
470
- loadLogs(currentPage);
 
 
 
471
  loadLogStats();
472
  }
473
 
 
48
  <label for="eventTypeFilter" class="form-label">Event Type</label>
49
  <select class="form-select" id="eventTypeFilter" name="event_type">
50
  <option value="">All Events</option>
51
+ <!-- Event types will be loaded dynamically -->
 
 
 
 
 
 
52
  </select>
53
  </div>
54
  <div class="col-md-4">
 
215
  };
216
 
217
  document.addEventListener('DOMContentLoaded', function() {
218
+ loadEventTypes();
219
  loadLogs();
220
  loadLogStats();
221
 
 
232
  });
233
  });
234
 
235
+ async function loadEventTypes() {
236
+ try {
237
+ const response = await axios.get('/ux/events/types', {
238
+ headers: {
239
+ 'Authorization': `Bearer {{ session.get("access_token", "") }}`
240
+ }
241
+ });
242
+
243
+ if (response.data.event_types) {
244
+ const select = document.getElementById('eventTypeFilter');
245
+ const currentValue = '{{ event_type_filter }}'; // Get selected value from template
246
+
247
+ // Keep the "All Events" option
248
+ select.innerHTML = '<option value="">All Events</option>';
249
+
250
+ // Add each event type as an option
251
+ response.data.event_types.forEach(eventType => {
252
+ const option = document.createElement('option');
253
+ option.value = eventType;
254
+
255
+ // Convert event_type to a more readable format
256
+ const displayName = eventType
257
+ .split('_')
258
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
259
+ .join(' ');
260
+
261
+ option.textContent = displayName;
262
+
263
+ // Set as selected if it matches the current filter
264
+ if (eventType === currentValue) {
265
+ option.selected = true;
266
+ }
267
+
268
+ select.appendChild(option);
269
+ });
270
+ }
271
+ } catch (error) {
272
+ console.error('Failed to load event types:', error);
273
+ }
274
+ }
275
+
276
  async function loadLogs(page = 1) {
277
  try {
278
  const params = new URLSearchParams({
 
503
  }
504
 
505
  function refreshLogs() {
506
+ // Re-apply any existing filters
507
+ applyFilters();
508
+
509
+ // Reload log statistics
510
  loadLogStats();
511
  }
512
 
web/events.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Blueprint, jsonify, session, request
2
+ from models import SystemLog, db
3
+ from logging_utils import log_event
4
+ from web.routes import login_required, is_admin_user_web
5
+
6
+ events_bp = Blueprint('events', __name__)
7
+
8
+ @events_bp.route('/ux/events/types')
9
+ @login_required
10
+ def get_event_types():
11
+ """Get all unique event types for filtering"""
12
+ if 'user_id' not in session:
13
+ return jsonify({'error': 'Unauthorized'}), 401
14
+
15
+ user_id = session['user_id']
16
+ is_admin = is_admin_user_web(user_id)
17
+
18
+ try:
19
+ # Base query - get distinct event types
20
+ query = db.session.query(SystemLog.event_type).distinct()
21
+
22
+ # Filter by user_id unless user is admin
23
+ if not is_admin:
24
+ query = query.filter(SystemLog.user_id == user_id)
25
+
26
+ # Execute query and get all event types
27
+ event_types = [event_type[0] for event_type in query.all() if event_type[0] is not None]
28
+
29
+ # Sort alphabetically
30
+ event_types.sort()
31
+
32
+ return jsonify({
33
+ 'event_types': event_types
34
+ })
35
+
36
+ except Exception as e:
37
+ log_event(
38
+ severity=3,
39
+ message=f"Failed to get event types: {str(e)}",
40
+ event_type="get_event_types_error",
41
+ user_id=session.get('user_id')
42
+ )
43
+ return jsonify({'error': str(e)}), 500