rosetta-ce 1.7.0__py3-none-any.whl → 1.7.1__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.

Potentially problematic release.


This version of rosetta-ce might be problematic. Click here for more details.

rosetta/rfaker.py CHANGED
@@ -401,7 +401,16 @@ class Events:
401
401
  required_fields: Optional[str] = None
402
402
  ) -> List[str]:
403
403
  """
404
- Generate fake syslog messages with optimizations for efficiency.
404
+ Generate fake syslog messages with per-message randomization.
405
+
406
+ Args:
407
+ count (int): Number of syslog messages to generate.
408
+ datetime_iso (Optional[datetime]): Starting datetime for the messages.
409
+ observables (Optional[Observables]): Observables object with predefined values.
410
+ required_fields (Optional[str]): Comma-separated string of required fields.
411
+
412
+ Returns:
413
+ List[str]: A list of generated syslog messages.
405
414
  """
406
415
  syslog_messages = []
407
416
  faker = Events.faker
@@ -416,43 +425,41 @@ class Events:
416
425
  "pid", "host", "user", "unix_process", "unix_cmd"
417
426
  ]
418
427
 
419
- # Precompute static values for required fields
420
- common_fields = {}
421
- for field in required_fields_list:
422
- value = None
423
- if observables and hasattr(observables, field):
424
- obs_value = getattr(observables, field)
425
- if obs_value:
426
- if isinstance(obs_value, list):
427
- value = random.choice(obs_value)
428
- else:
429
- value = obs_value
430
- if value is None:
431
- value = Events._set_field(field)
432
- common_fields[field] = value
433
-
434
- # Preprocess observables
435
- extra_fields = []
436
- if observables:
437
- observables_dict = vars(observables)
438
- for key, value in observables_dict.items():
439
- if value and key not in required_fields_list:
440
- if isinstance(value, list):
441
- val = random.choice(value)
442
- else:
443
- val = value
444
- extra_fields.append(str(val))
428
+ # Convert observables to a dictionary for easy access
429
+ observables_dict = vars(observables) if observables else {}
430
+
431
+ # Precompute constant fields (if any)
432
+ # For syslog, most fields may vary per message, so we may not have many constants
433
+ constant_fields = {}
445
434
 
446
- # Generate all syslog messages
435
+ # Generate syslog messages
447
436
  for i in range(count):
448
437
  # Update datetime for each log
449
438
  current_time = (datetime_iso + timedelta(seconds=i + 1)).strftime('%b %d %H:%M:%S')
450
439
 
451
- # Build the syslog message efficiently
440
+ # Generate required fields per message
441
+ event_fields = {}
442
+ for field in required_fields_list:
443
+ value = None
444
+ if field in observables_dict and observables_dict[field]:
445
+ obs_value = observables_dict[field]
446
+ value = random.choice(obs_value) if isinstance(obs_value, list) else obs_value
447
+ else:
448
+ value = Events._set_field(field)
449
+ event_fields[field] = value
450
+
451
+ # Generate extra fields per message
452
+ extra_fields = []
453
+ for key, value in observables_dict.items():
454
+ if value and key not in required_fields_list:
455
+ val = random.choice(value) if isinstance(value, list) else value
456
+ extra_fields.append(str(val))
457
+
458
+ # Build the syslog message
452
459
  syslog_message_parts = [f"{current_time}"]
453
460
 
454
461
  # Insert required fields
455
- syslog_message_parts.extend(str(common_fields[field]) for field in required_fields_list)
462
+ syslog_message_parts.extend(str(event_fields[field]) for field in required_fields_list)
456
463
 
457
464
  # Append additional observables not in required fields
458
465
  syslog_message_parts.extend(extra_fields)
@@ -460,7 +467,7 @@ class Events:
460
467
  syslog_messages.append(" ".join(syslog_message_parts))
461
468
 
462
469
  return syslog_messages
463
-
470
+
464
471
  @classmethod
465
472
  def cef(
466
473
  cls,
@@ -473,7 +480,7 @@ class Events:
473
480
  required_fields: Optional[str] = None
474
481
  ) -> List[str]:
475
482
  cef_messages = []
476
- faker = Events.faker
483
+ faker = Events.faker
477
484
  vendor = vendor or faker.company()
478
485
  product = product or faker.word()
479
486
  version = version or faker.numerify("1.0.#")
@@ -481,54 +488,47 @@ class Events:
481
488
  required_fields_list = required_fields.split(",") if required_fields else [
482
489
  "local_ip", "local_port", "remote_ip", "remote_port", "protocol", "rule_id", "action"
483
490
  ]
484
-
485
- common_fields = {}
486
- for field in required_fields_list:
487
- value = None
488
- if observables and hasattr(observables, field):
489
- obs_value = getattr(observables, field)
490
- if obs_value:
491
- if isinstance(obs_value, list):
492
- value = random.choice(obs_value)
493
- else:
494
- value = obs_value
495
- if value is None:
496
- value = Events._set_field(field)
497
- common_fields[field] = value
498
-
499
-
500
- # Preprocess observables
501
- extra_fields_str = ""
502
- if observables:
503
- observables_dict = vars(observables)
504
- extra_fields = [
505
- f"{key}={random.choice(value)}"
506
- for key, value in observables_dict.items()
507
- if value and key not in required_fields_list
508
- ]
509
- if extra_fields:
510
- extra_fields_str = " " + " ".join(extra_fields)
511
-
512
- # Pre-compile the CEF message template
513
- cef_template = (
514
- f"CEF:0|{vendor}|{product}|{version}|{{log_id}}|{{current_datetime}}|{{severity}}|"
515
- + " ".join([f"{field}={common_fields[field]}" for field in required_fields_list])
516
- )
517
-
491
+
492
+ # Convert observables to a dictionary for easy access
493
+ observables_dict = vars(observables) if observables else {}
494
+
518
495
  # Generate events
519
496
  for i in range(count):
520
497
  current_datetime = datetime_iso + timedelta(seconds=i)
521
498
  log_id = faker.uuid4()
522
- severity = common_fields.get('severity') or 'low'
523
-
524
- cef_message = cef_template.format(
525
- log_id=log_id,
526
- current_datetime=current_datetime.strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
527
- severity=severity
499
+ severity = 'low' # Or generate per message if needed
500
+
501
+ # Generate field values per message
502
+ event_fields = {}
503
+ for field in required_fields_list:
504
+ value = None
505
+ if field in observables_dict and observables_dict[field]:
506
+ obs_value = observables_dict[field]
507
+ if isinstance(obs_value, list):
508
+ value = random.choice(obs_value)
509
+ else:
510
+ value = obs_value
511
+ else:
512
+ value = Events._set_field(field)
513
+ event_fields[field] = value
514
+
515
+ # Generate extra fields per message
516
+ extra_fields = []
517
+ for key, value in observables_dict.items():
518
+ if value and key not in required_fields_list:
519
+ val = random.choice(value) if isinstance(value, list) else value
520
+ extra_fields.append(f"{key}={val}")
521
+
522
+ extra_fields_str = " " + " ".join(extra_fields) if extra_fields else ""
523
+
524
+ # Build the CEF message
525
+ cef_message = (
526
+ f"CEF:0|{vendor}|{product}|{version}|{log_id}|{current_datetime.strftime('%Y-%m-%dT%H:%M:%S.%fZ')}|{severity}|"
527
+ + " ".join([f"{field}={event_fields[field]}" for field in required_fields_list])
528
528
  )
529
529
  cef_message += extra_fields_str
530
530
  cef_messages.append(cef_message)
531
-
531
+
532
532
  return cef_messages
533
533
 
534
534
  @classmethod
@@ -543,10 +543,10 @@ class Events:
543
543
  required_fields: Optional[str] = None
544
544
  ) -> List[str]:
545
545
  """
546
- Generates optimized fake LEEF (Log Event Extended Format) messages.
546
+ Generates optimized fake LEEF (Log Event Extended Format) messages with per-message randomization.
547
547
  """
548
548
  leef_messages = []
549
- faker = Events.faker
549
+ faker = Events.faker
550
550
  vendor = vendor or faker.company()
551
551
  product = product or faker.word()
552
552
  version = version or faker.numerify("1.0.#")
@@ -557,50 +557,56 @@ class Events:
557
557
  "local_ip", "local_port", "host", "url", "protocol", "response_code", "action"
558
558
  ]
559
559
 
560
- # Precompute event_id and severity
561
- event_id = faker.random_int(min=101, max=501)
562
- severity = Events._set_field("severity")
563
-
564
- # Precompute common fields
565
- common_fields = {}
566
- for field in required_fields_list:
567
- value = None
568
- if observables and hasattr(observables, field):
569
- obs_value = getattr(observables, field)
570
- if obs_value:
571
- if isinstance(obs_value, list):
572
- value = random.choice(obs_value)
573
- else:
574
- value = obs_value
575
- if value is None:
576
- value = Events._set_field(field)
577
- common_fields[field] = value
578
-
579
- # Preprocess extra observables
580
- extra_fields = []
581
- if observables:
582
- observables_dict = vars(observables)
583
- for key, value in observables_dict.items():
584
- if value and key not in required_fields_list:
585
- val = random.choice(value) if isinstance(value, list) else value
586
- extra_fields.append(f" {key}={val}")
560
+ # Convert observables to a dictionary for easy access
561
+ observables_dict = vars(observables) if observables else {}
587
562
 
588
- # Pre-compile the LEEF message template
589
- leef_template = (
590
- f"LEEF:1.0|{vendor}|{product}|{version}|{event_id}|"
591
- f"severity={severity} devTime={{current_datetime}}"
592
- + "".join(f" {field}={common_fields[field]}" for field in required_fields_list)
593
- + "".join(extra_fields)
594
- )
563
+ # Precompute constant fields
564
+ # Event ID and severity might change per event; move inside the loop if needed
565
+ constant_fields = {
566
+ 'vendor': vendor,
567
+ 'product': product,
568
+ 'version': version,
569
+ }
595
570
 
596
571
  # Generate messages
597
572
  for i in range(count):
598
573
  current_datetime = (datetime_iso + timedelta(seconds=i)).strftime('%b %d %H:%M:%S')
599
574
 
600
- leef_message = leef_template.format(current_datetime=current_datetime)
575
+ # Generate per-message fields
576
+ # Event ID and severity could be variable
577
+ event_id = Events._set_field("event_id")
578
+ severity = Events._set_field("severity")
579
+
580
+ # Generate required fields per message
581
+ event_fields = {}
582
+ for field in required_fields_list:
583
+ value = None
584
+ if field in observables_dict and observables_dict[field]:
585
+ obs_value = observables_dict[field]
586
+ value = random.choice(obs_value) if isinstance(obs_value, list) else obs_value
587
+ else:
588
+ value = Events._set_field(field)
589
+ event_fields[field] = value
590
+
591
+ # Generate extra fields per message
592
+ extra_fields = []
593
+ for key, value in observables_dict.items():
594
+ if value and key not in required_fields_list:
595
+ val = random.choice(value) if isinstance(value, list) else value
596
+ extra_fields.append(f" {key}={val}")
597
+
598
+ # Build the LEEF message
599
+ leef_message = (
600
+ f"LEEF:1.0|{constant_fields['vendor']}|{constant_fields['product']}|{constant_fields['version']}|{event_id}|"
601
+ f"severity={severity} devTime={current_datetime}"
602
+ + "".join(f" {field}={event_fields[field]}" for field in required_fields_list)
603
+ + "".join(extra_fields)
604
+ )
605
+
601
606
  leef_messages.append(leef_message)
602
607
 
603
608
  return leef_messages
609
+
604
610
 
605
611
  @classmethod
606
612
  def winevent(
@@ -610,7 +616,7 @@ class Events:
610
616
  observables: Optional['Observables'] = None
611
617
  ) -> List[str]:
612
618
  """
613
- Generates optimized fake Windows Event Log messages using set_field.
619
+ Generates fake Windows Event Log messages with per-message randomization.
614
620
 
615
621
  Args:
616
622
  count (int): The number of fake messages to generate.
@@ -649,26 +655,13 @@ class Events:
649
655
  "src_domain"
650
656
  ]
651
657
 
652
- # Precompute common fields using set_field
653
- common_fields = {}
654
- for field in required_fields_list:
655
- value = None
656
- if observables and hasattr(observables, field):
657
- obs_value = getattr(observables, field)
658
- if obs_value:
659
- value = random.choice(obs_value) if isinstance(obs_value, list) else obs_value
660
- if value is None:
661
- value = Events._set_field(field)
662
- common_fields[field] = value
663
-
664
- # Preprocess extra observables not in required fields
665
- extra_fields = {}
666
- if observables:
667
- observables_dict = vars(observables)
668
- for key, value in observables_dict.items():
669
- if value and key not in required_fields_list:
670
- val = random.choice(value) if isinstance(value, list) else value
671
- extra_fields[key] = val
658
+ # Convert observables to a dictionary for easy access
659
+ observables_dict = vars(observables) if observables else {}
660
+
661
+ # Precompute constant fields (if any)
662
+ constant_fields = {
663
+ # Add any fields that are constant across events
664
+ }
672
665
 
673
666
  # Generate events
674
667
  for i in range(count):
@@ -677,23 +670,46 @@ class Events:
677
670
  system_time = current_datetime.strftime('%Y-%m-%d %H:%M:%S')
678
671
 
679
672
  # Generate per-event fields
673
+ event_fields = {}
674
+
675
+ # Generate required fields per message
676
+ for field in required_fields_list:
677
+ value = None
678
+ if field in observables_dict and observables_dict[field]:
679
+ obs_value = observables_dict[field]
680
+ value = random.choice(obs_value) if isinstance(obs_value, list) else obs_value
681
+ else:
682
+ value = Events._set_field(field)
683
+ event_fields[field] = value
684
+
685
+ # Generate extra fields per message
686
+ for key, value in observables_dict.items():
687
+ if value and key not in required_fields_list:
688
+ val = random.choice(value) if isinstance(value, list) else value
689
+ event_fields[key] = val
690
+
691
+ # Generate per-event fields that are not in observables
680
692
  guid = faker.uuid4()
681
693
 
682
694
  # Use event_id from observables if available
683
- event_record_id = None
684
- if observables and hasattr(observables, 'event_id') and observables.event_id:
685
- event_record_id = random.choice(observables.event_id)
695
+ if 'event_id' in observables_dict and observables_dict['event_id']:
696
+ event_record_id = (
697
+ random.choice(observables_dict['event_id'])
698
+ if isinstance(observables_dict['event_id'], list)
699
+ else observables_dict['event_id']
700
+ )
686
701
  else:
687
702
  event_record_id = Events._set_field('event_id')
688
703
 
689
704
  # Prepare event fields
690
- event_fields = {
705
+ event_fields.update({
691
706
  'guid': guid,
692
707
  'system_time': system_time,
693
708
  'event_record_id': event_record_id,
694
- **common_fields,
695
- **extra_fields
696
- }
709
+ })
710
+
711
+ # Combine with any constant fields
712
+ event_fields.update(constant_fields)
697
713
 
698
714
  # Select a random event template
699
715
  unformatted_event = random.choice(WIN_EVENTS)
@@ -704,7 +720,7 @@ class Events:
704
720
  winevent_messages.append(win_event)
705
721
 
706
722
  return winevent_messages
707
-
723
+
708
724
  @classmethod
709
725
  def json(
710
726
  cls,
@@ -717,63 +733,80 @@ class Events:
717
733
  required_fields: Optional[str] = None
718
734
  ) -> List[dict]:
719
735
  """
720
- Generate optimized fake JSON messages representing discovered vulnerabilities.
736
+ Generate fake JSON messages representing discovered vulnerabilities with per-message randomization.
737
+
738
+ Args:
739
+ count (int): Number of JSON messages to generate.
740
+ datetime_iso (Optional[datetime]): Starting datetime for the messages.
741
+ vendor (Optional[str]): Vendor name.
742
+ product (Optional[str]): Product name.
743
+ version (Optional[str]): Product version.
744
+ observables (Optional[Observables]): Observables object with predefined values.
745
+ required_fields (Optional[str]): Comma-separated string of required fields.
746
+
747
+ Returns:
748
+ List[dict]: A list of generated JSON messages.
721
749
  """
722
750
  json_messages = []
723
- faker = Events.faker
751
+ faker = Events.faker
724
752
 
725
753
  # Precompute vendor, product, and version details
726
754
  vendor = vendor or faker.company()
727
755
  product = product or "UnknownProduct"
728
756
  version = version or faker.numerify("1.0.#")
729
757
 
730
- # Set initial datetime and precompute required fields if not provided
758
+ # Set initial datetime
731
759
  datetime_iso = datetime_iso or datetime.now() - timedelta(hours=1)
732
- required_fields_list = required_fields.split(",") if required_fields else (
733
- ["cve_id", "host", "file_hash"] if product == "VulnScanner" else ["user", "host"]
734
- )
735
-
736
- # Precompute static fields
737
- severity = Events._set_field("severity")
738
- common_fields = {}
739
- for field in required_fields_list:
740
- value = None
741
- if observables and hasattr(observables, field):
742
- obs_value = getattr(observables, field)
743
- if obs_value:
744
- if isinstance(obs_value, list):
745
- value = random.choice(obs_value)
746
- else:
747
- value = obs_value
748
- if value is None:
749
- value = Events._set_field(field)
750
- common_fields[field] = value
751
-
752
- # Preprocess additional observables not in required_fields
753
- extra_fields = {}
754
- if observables:
755
- observables_dict = vars(observables)
756
- for key, value in observables_dict.items():
757
- if value and key not in required_fields_list:
758
- val = random.choice(value) if isinstance(value, list) else value
759
- extra_fields[key] = val
760
760
 
761
- # Loop to generate JSON events
761
+ # Set required fields
762
+ if required_fields:
763
+ required_fields_list = required_fields.split(",")
764
+ else:
765
+ required_fields_list = (
766
+ ["cve_id", "host", "file_hash"] if product == "VulnScanner" else ["user", "host"]
767
+ )
768
+
769
+ # Convert observables to a dictionary for easy access
770
+ observables_dict = vars(observables) if observables else {}
771
+
772
+ # Precompute constant fields
773
+ constant_fields = {
774
+ 'vendor': vendor,
775
+ 'product': product,
776
+ 'version': version,
777
+ }
778
+
779
+ # Generate JSON events
762
780
  for i in range(count):
763
781
  # Adjust datetime for each message
764
782
  current_datetime = datetime_iso + timedelta(seconds=i)
783
+ datetime_str = current_datetime.strftime("%Y-%m-%d %H:%M:%S")
765
784
 
766
- # Initialize event with static fields
767
- event = {
768
- 'vendor': vendor,
769
- 'product': product,
770
- 'version': version,
771
- 'datetime_iso': current_datetime.strftime("%Y-%m-%d %H:%M:%S"),
772
- 'severity': severity,
773
- **common_fields,
774
- **extra_fields
785
+ # Generate variable fields per message
786
+ event_fields = {
787
+ 'datetime_iso': datetime_str,
788
+ 'severity': Events._set_field('severity'),
775
789
  }
776
790
 
791
+ # Generate required fields per message
792
+ for field in required_fields_list:
793
+ value = None
794
+ if field in observables_dict and observables_dict[field]:
795
+ obs_value = observables_dict[field]
796
+ value = random.choice(obs_value) if isinstance(obs_value, list) else obs_value
797
+ else:
798
+ value = Events._set_field(field)
799
+ event_fields[field] = value
800
+
801
+ # Include additional observables not in required fields
802
+ for key, value in observables_dict.items():
803
+ if value and key not in required_fields_list:
804
+ val = random.choice(value) if isinstance(value, list) else value
805
+ event_fields[key] = val
806
+
807
+ # Combine all fields into the event
808
+ event = {**constant_fields, **event_fields}
809
+
777
810
  # Append generated event to the list
778
811
  json_messages.append(event)
779
812
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: rosetta-ce
3
- Version: 1.7.0
3
+ Version: 1.7.1
4
4
  Summary: Rosetta is a Python package that can be used to fake security logs and alerts for testing different detection and response use cases.
5
5
  Home-page: https://github.com/ayman-m/rosetta
6
6
  Author: Ayman Mahmoud
@@ -1,6 +1,6 @@
1
1
  rosetta/__init__.py,sha256=9rqZF7bpDMRN5H-rjNRUfzQAOIqyc21hTTZfYufTy04,92
2
2
  rosetta/rconverter.py,sha256=oPdWMtO6_aeQC8PqCl4nHKEpVb1kaBACSaNXsz-o00Q,3008
3
- rosetta/rfaker.py,sha256=aN6udv5W8ZduEXzgiFbElYUK1p4i_VUpJk5qcYPG6fk,36608
3
+ rosetta/rfaker.py,sha256=Ve7D-swOdN8dyTTZM1L2jXh7SCRfq6oLG_E1qVTT5mE,38446
4
4
  rosetta/rsender.py,sha256=Zfj9MVckO49iabxCQ19fkGKpKnzOXB1iHOTb9CgkzsE,10463
5
5
  rosetta/constants/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  rosetta/constants/attributes.py,sha256=dxPzi5D00U8Fvo1B1u1bC5-kYqN3lCIpYwwroHHp-hw,4622
@@ -8,8 +8,8 @@ rosetta/constants/db.py,sha256=ZobruGzgijbbFHEnLGuwVwZTxLCBL-_vdmUDPVv3OAo,4708
8
8
  rosetta/constants/sensors.py,sha256=ZxPWFrNqDFKRVn9ai-5vtvIiU4-3FAXQIRj7gFoBRPk,1936
9
9
  rosetta/constants/sources.py,sha256=b3ynlKGw1gw7VBA4yCYkJ7aq4vVPfypqA8W_kuAZaBA,1658
10
10
  rosetta/constants/systems.py,sha256=LxrokxCqv-CKTSEK8199Qxlv5eSKAvp2OYKI28o-Lpw,7403
11
- rosetta_ce-1.7.0.dist-info/LICENSE,sha256=jF5fCbmI1A-yyvPAEeQ5VHM094tRLlWsMyun-UlX-pQ,1070
12
- rosetta_ce-1.7.0.dist-info/METADATA,sha256=l6ZX4zYQfe3Qh6DKD384h3AyFXJsgM7CzET-rtpEmzY,11321
13
- rosetta_ce-1.7.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
14
- rosetta_ce-1.7.0.dist-info/top_level.txt,sha256=HLxDc6BJxHZDzVIlOwpCGH0DqIf65OhZcHniRDaUUZc,8
15
- rosetta_ce-1.7.0.dist-info/RECORD,,
11
+ rosetta_ce-1.7.1.dist-info/LICENSE,sha256=jF5fCbmI1A-yyvPAEeQ5VHM094tRLlWsMyun-UlX-pQ,1070
12
+ rosetta_ce-1.7.1.dist-info/METADATA,sha256=-6hMIFZXghZcjb9oHRMxIxcE02SSFAT0IJDVf8oI65M,11321
13
+ rosetta_ce-1.7.1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
14
+ rosetta_ce-1.7.1.dist-info/top_level.txt,sha256=HLxDc6BJxHZDzVIlOwpCGH0DqIf65OhZcHniRDaUUZc,8
15
+ rosetta_ce-1.7.1.dist-info/RECORD,,