rosetta-ce 1.4.8__py3.11.egg → 1.5.0__py3.11.egg

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.

EGG-INFO/PKG-INFO CHANGED
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: rosetta-ce
3
- Version: 1.4.8
3
+ Version: 1.5.0
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
Binary file
Binary file
rosetta/rfaker.py CHANGED
@@ -434,14 +434,14 @@ class Events:
434
434
  return field_value
435
435
 
436
436
  @classmethod
437
- def syslog(cls, count: int, timestamp: Optional[datetime] = None, observables: Optional[Observables] = None,
437
+ def syslog(cls, count: int, datetime_iso: Optional[datetime] = None, observables: Optional[Observables] = None,
438
438
  required_fields: Optional[str] = None) -> List[str]:
439
439
  """
440
440
  Generate fake syslog messages.
441
441
 
442
442
  Args:
443
443
  count: The number of syslog messages to generate.
444
- timestamp: Optional. The starting timestamp for the syslog messages. If not provided, a random time during
444
+ datetime_iso: Optional. The starting datetime_iso for the syslog messages. If not provided, a random time during
445
445
  the past hour from now will be used.
446
446
  observables: Optional. An observables object. If not provided, random objservable will be generated
447
447
  and used.
@@ -461,14 +461,14 @@ class Events:
461
461
  """
462
462
  syslog_messages = []
463
463
  faker = cls._create_faker()
464
- if timestamp is None:
465
- timestamp = datetime.now() - timedelta(hours=1)
466
- timestamp += timedelta(seconds=faker.random_int(min=0, max=3599))
464
+ if datetime_iso is None:
465
+ datetime_iso = datetime.now() - timedelta(hours=1)
466
+ datetime_iso += timedelta(seconds=faker.random_int(min=0, max=3599))
467
467
  if not required_fields:
468
468
  required_fields = "pid,host,user,unix_process,unix_cmd"
469
469
  for i in range(count):
470
- timestamp += timedelta(seconds=1)
471
- syslog_message = f"{timestamp.strftime('%Y-%m-%d %H:%M:%S')}"
470
+ datetime_iso += timedelta(seconds=1)
471
+ syslog_message = f"{datetime_iso.strftime('%Y-%m-%d %H:%M:%S')}"
472
472
  for field in required_fields.split(","):
473
473
  syslog_message += f" {cls.set_field(field, observables)}"
474
474
  if observables:
@@ -480,14 +480,14 @@ class Events:
480
480
 
481
481
  @classmethod
482
482
  def cef(cls, count: int, vendor: Optional[str] = None, product: Optional[str] = None,
483
- version: Optional[str] = None, timestamp: Optional[datetime] = None,
483
+ version: Optional[str] = None, datetime_iso: Optional[datetime] = None,
484
484
  observables: Optional[Observables] = None, required_fields: Optional[str] = None) -> List[str]:
485
485
  """
486
486
  Generates fake CEF (Common Event Format) messages.
487
487
 
488
488
  Args:
489
489
  count: The number of CEF messages to generate.
490
- timestamp: Optional. The starting timestamp for the syslog messages. If not provided, a random time during.
490
+ datetime_iso: Optional. The starting datetime_iso for the syslog messages. If not provided, a random time during.
491
491
  vendor: Optional. The vendor.
492
492
  product: Optional. The product value options include:
493
493
  - Firewall
@@ -519,9 +519,9 @@ class Events:
519
519
  faker = cls._create_faker()
520
520
  vendor = vendor or faker.company()
521
521
  version = version or faker.numerify("1.0.#")
522
- if timestamp is None:
523
- timestamp = datetime.now() - timedelta(hours=1)
524
- timestamp += timedelta(seconds=faker.random_int(min=0, max=3599))
522
+ if datetime_iso is None:
523
+ datetime_iso = datetime.now() - timedelta(hours=1)
524
+ datetime_iso += timedelta(seconds=faker.random_int(min=0, max=3599))
525
525
  if not required_fields:
526
526
  if product == "Firewall":
527
527
  required_fields = "local_ip,local_port,remote_ip,remote_port,dst_url,inbound_bytes," \
@@ -532,8 +532,8 @@ class Events:
532
532
  else:
533
533
  required_fields = "local_ip,local_port,remote_ip,remote_port,protocol,rule_id,action"
534
534
  for i in range(count):
535
- timestamp += timedelta(seconds=1)
536
- cef_message = f"CEF:0|{vendor}|{product}|{version}|{cls.set_field('log_id', observables)}|{timestamp}" \
535
+ datetime_iso += timedelta(seconds=1)
536
+ cef_message = f"CEF:0|{vendor}|{product}|{version}|{cls.set_field('log_id', observables)}|{datetime_iso}" \
537
537
  f"|{cls.set_field('severity', observables)}|"
538
538
  for field in required_fields.split(","):
539
539
  cef_message += f" {field}={cls.set_field(field, observables)}"
@@ -545,7 +545,7 @@ class Events:
545
545
  return cef_messages
546
546
 
547
547
  @classmethod
548
- def leef(cls, count, timestamp: Optional[datetime] = None, vendor: Optional[str] = None,
548
+ def leef(cls, count, datetime_iso: Optional[datetime] = None, vendor: Optional[str] = None,
549
549
  product: Optional[str] = None, version: Optional[str] = None,
550
550
  observables: Optional[Observables] = None, required_fields: Optional[str] = None) -> List[str]:
551
551
  """
@@ -553,7 +553,7 @@ class Events:
553
553
 
554
554
  Parameters:
555
555
  count (int): The number of LEEF messages to generate.
556
- timestamp: Optional. The starting timestamp for the syslog messages. If not provided, a random time during.
556
+ datetime_iso: Optional. The starting datetime_iso for the syslog messages. If not provided, a random time during.
557
557
  vendor: Optional. The vendor.
558
558
  product: Optional. The product.
559
559
  version: Optional. The version.
@@ -583,9 +583,9 @@ class Events:
583
583
  faker = cls._create_faker()
584
584
  vendor = vendor or faker.company()
585
585
  version = version or faker.numerify("1.0.#")
586
- if timestamp is None:
587
- timestamp = datetime.now() - timedelta(hours=1)
588
- timestamp += timedelta(seconds=faker.random_int(min=0, max=3599))
586
+ if datetime_iso is None:
587
+ datetime_iso = datetime.now() - timedelta(hours=1)
588
+ datetime_iso += timedelta(seconds=faker.random_int(min=0, max=3599))
589
589
  if not required_fields:
590
590
  if product == "WAF":
591
591
  required_fields = "local_ip,local_port,host,method,url,protocol," \
@@ -593,8 +593,8 @@ class Events:
593
593
  else:
594
594
  required_fields = "local_ip,local_port,host,url,protocol,response_code,action"
595
595
  for i in range(count):
596
- timestamp += timedelta(seconds=1)
597
- leef_message = f"LEEF:1.0|{vendor}|{product}|{version}|deviceEventDate={timestamp}|" \
596
+ datetime_iso += timedelta(seconds=1)
597
+ leef_message = f"LEEF:1.0|{vendor}|{product}|{version}|deviceEventDate={datetime_iso}|" \
598
598
  f"severity={cls.set_field('severity', observables)}|"
599
599
  for field in required_fields.split(","):
600
600
  leef_message += f" {field}={cls.set_field(field, observables)}"
@@ -606,14 +606,14 @@ class Events:
606
606
  return leef_messages
607
607
 
608
608
  @classmethod
609
- def winevent(cls, count, timestamp: Optional[datetime] = None, observables: Optional[Observables] = None) -> \
609
+ def winevent(cls, count, datetime_iso: Optional[datetime] = None, observables: Optional[Observables] = None) -> \
610
610
  List[str]:
611
611
  """
612
612
  Generates fake Windows Event Log messages.
613
613
 
614
614
  Args:
615
615
  count (int): The number of fake messages to generate.
616
- timestamp: Optional. The starting timestamp for the syslog messages. If not provided, a random time during
616
+ datetime_iso: Optional. The starting datetime_iso for the syslog messages. If not provided, a random time during
617
617
  observables: An observables object. If not provided, random objservable will be generated and used.
618
618
 
619
619
  Returns:
@@ -625,15 +625,15 @@ class Events:
625
625
  """
626
626
  winevent_messages = []
627
627
  faker = cls._create_faker()
628
- if timestamp is None:
629
- timestamp = datetime.now() - timedelta(hours=1)
630
- timestamp += timedelta(seconds=faker.random_int(min=0, max=3599))
628
+ if datetime_iso is None:
629
+ datetime_iso = datetime.now() - timedelta(hours=1)
630
+ datetime_iso += timedelta(seconds=faker.random_int(min=0, max=3599))
631
631
  for i in range(count):
632
- timestamp += timedelta(seconds=1)
632
+ datetime_iso += timedelta(seconds=1)
633
633
  guid = faker.uuid4()
634
634
  local_port = faker.random_int(min=1024, max=65535)
635
635
  transmitted_services = faker.sentence(nb_words=5)
636
- system_time = timestamp
636
+ system_time = datetime_iso
637
637
  process_id = faker.random_int()
638
638
  new_process_id = faker.random_int()
639
639
  thread_id = faker.random_int()
@@ -671,7 +671,7 @@ class Events:
671
671
  return winevent_messages
672
672
 
673
673
  @classmethod
674
- def json(cls, count, timestamp: Optional[datetime] = None, vendor: Optional[str] = None,
674
+ def json(cls, count, datetime_iso: Optional[datetime] = None, vendor: Optional[str] = None,
675
675
  product: Optional[str] = None, version: Optional[str] = None, observables: Optional[Observables] = None,
676
676
  required_fields: Optional[str] = None) -> List[dict]:
677
677
  """
@@ -679,7 +679,7 @@ class Events:
679
679
 
680
680
  Args:
681
681
  count (int): The number of JSON messages to generate.
682
- timestamp: Optional. The starting timestamp for the syslog messages. If not provided, a random time during.
682
+ datetime_iso: Optional. The starting datetime_iso for the syslog messages. If not provided, a random time during.
683
683
  vendor: Optional. The vendor.
684
684
  product: Optional. The product value options include:
685
685
  - VulnScanner
@@ -702,21 +702,21 @@ class Events:
702
702
  faker = cls._create_faker()
703
703
  vendor = vendor or faker.company()
704
704
  version = version or faker.numerify("1.0.#")
705
- if timestamp is None:
706
- timestamp = datetime.now() - timedelta(hours=1)
707
- timestamp += timedelta(seconds=faker.random_int(min=0, max=3599))
705
+ if datetime_iso is None:
706
+ datetime_iso = datetime.now() - timedelta(hours=1)
707
+ datetime_iso += timedelta(seconds=faker.random_int(min=0, max=3599))
708
708
  if not required_fields:
709
709
  if product == "VulnScanner":
710
710
  required_fields = "cve_id,host,file_hash"
711
711
  else:
712
712
  required_fields = "user,host"
713
713
  for i in range(count):
714
- timestamp += timedelta(seconds=1)
714
+ datetime_iso += timedelta(seconds=1)
715
715
  event = {
716
716
  'vendor': vendor,
717
717
  'product': product,
718
718
  'version': version,
719
- 'timestamp': str(timestamp),
719
+ 'datetime_iso': str(datetime_iso),
720
720
  'severity': cls.set_field("severity", observables)
721
721
  }
722
722
  for field in required_fields.split(","):
@@ -729,7 +729,7 @@ class Events:
729
729
  return json_messages
730
730
 
731
731
  @classmethod
732
- def incidents(cls, count, fields: Optional[str] = None, timestamp: Optional[datetime] = None,
732
+ def incidents(cls, count, fields: Optional[str] = None, datetime_iso: Optional[datetime] = None,
733
733
  vendor: Optional[str] = None, product: Optional[str] = None, version: Optional[str] = None,
734
734
  observables: Optional[Observables] = None, required_fields: Optional[str] = None) -> List[dict]:
735
735
  """
@@ -743,7 +743,7 @@ class Events:
743
743
  vendor: Optional. The vendor.
744
744
  product: Optional. The product.
745
745
  version: Optional. The version.
746
- timestamp: Optional. The starting timestamp for the syslog messages. If not provided, a random time during
746
+ datetime_iso: Optional. The starting datetime_iso for the syslog messages. If not provided, a random time during
747
747
  observables: An observables object. If not provided, random objservable will be generated and used.
748
748
  required_fields: Optional. A list of fields that are required to present in the generated data, whether from
749
749
  observables or randomely.
@@ -816,14 +816,14 @@ class Events:
816
816
  incident['description'] = incident_description
817
817
  if 'events' in field_list:
818
818
  incident['events'] = [
819
- {"event": cls.syslog(count=1, timestamp=timestamp, observables=observables,
819
+ {"event": cls.syslog(count=1, datetime_iso=datetime_iso, observables=observables,
820
820
  required_fields=required_fields)[0]},
821
- {"event": cls.cef(count=1, timestamp=timestamp, vendor=vendor, product=product, version=version
821
+ {"event": cls.cef(count=1, datetime_iso=datetime_iso, vendor=vendor, product=product, version=version
822
822
  , observables=observables, required_fields=required_fields)[0]},
823
- {"event": cls.leef(count=1, timestamp=timestamp, vendor=vendor, product=product,
823
+ {"event": cls.leef(count=1, datetime_iso=datetime_iso, vendor=vendor, product=product,
824
824
  version=version, observables=observables, required_fields=required_fields)[0]},
825
- {"event": cls.winevent(count=1, timestamp=timestamp, observables=observables)[0]},
826
- {"event": cls.json(count=1, timestamp=timestamp, vendor=vendor, product=product,
825
+ {"event": cls.winevent(count=1, datetime_iso=datetime_iso, observables=observables)[0]},
826
+ {"event": cls.json(count=1, datetime_iso=datetime_iso, vendor=vendor, product=product,
827
827
  version=version, observables=observables,
828
828
  required_fields=required_fields)[0]}
829
829
  ]
rosetta/rsender.py CHANGED
@@ -55,11 +55,13 @@ class Sender:
55
55
  None.
56
56
  """
57
57
 
58
- def __init__(self, data_type: str, destination: str,
58
+ def __init__(self, data_type: str, destination: str, headers: Optional[dict] = None,
59
59
  worker_name: Optional[str] = 'worker_'+str(datetime.now()), count: Optional[int] = 1,
60
60
  interval: Optional[int] = 1, vendor: Optional[str] = None, product: Optional[str] = None,
61
- version: Optional[str] = None, observables: Optional[Observables] = None, fields: Optional[str] = None,
62
- verify_ssl: Optional[bool] = None, datetime_obj: Optional[datetime] = None):
61
+ version: Optional[str] = None, required_fields: Optional[str] = None,
62
+ observables: Optional[Observables] = None, fields: Optional[str] = None,
63
+ verify_ssl: Optional[bool] = None, datetime_obj: Optional[datetime] = None,
64
+ data_json: Optional[dict] = None, data_text: Optional[str] = None):
63
65
  """
64
66
  Constructor for DataSenderWorker class.
65
67
 
@@ -77,12 +79,21 @@ class Sender:
77
79
  :param vendor: Optional. The vendor.
78
80
  :param product: Optional. The product.
79
81
  :param version: Optional. The version.
80
- :param observables: Observables, list of observables.
81
- :param fields: str, comma-separated list of fields to include in incident data.
82
- :param verify_ssl: bool, handling ssl verification errors.
82
+ :param required_fields: Optional. A list of fields that are required to present in the generated data, whether
83
+ from observables or randomely.
84
+ :param observables: Optional. Observables, list of observables.
85
+ :param fields: Optional. comma-separated list of fields to include in incident data.
86
+ :param verify_ssl: Optional. handling ssl verification errors.
87
+ :param datetime_obj: Optional. time to start from.
88
+ :param data_json: Optional. JSON data to send.
89
+ :param data_text: Optional. Text data to send.
83
90
 
84
91
  :return: None
85
92
  """
93
+ if headers is None:
94
+ self.headers = {}
95
+ else:
96
+ self.headers = headers
86
97
  self.thread = None
87
98
  self.worker_name = worker_name
88
99
  self.data_type = data_type
@@ -91,6 +102,7 @@ class Sender:
91
102
  self.vendor = vendor
92
103
  self.product = product
93
104
  self.version = version
105
+ self.required_fields = required_fields
94
106
  self.destination = destination
95
107
  self.created_at = datetime.now()
96
108
  self.status = "Stopped"
@@ -98,6 +110,8 @@ class Sender:
98
110
  self.fields = fields
99
111
  self.verify_ssl = verify_ssl
100
112
  self.datetime_obj = datetime_obj
113
+ self.data_json = data_json
114
+ self.data_text = data_text
101
115
 
102
116
  def start(self) -> str:
103
117
  """
@@ -137,16 +151,21 @@ class Sender:
137
151
  try:
138
152
  self.count -= 1
139
153
  if self.data_type in ["SYSLOG", "CEF", "LEEF"]:
140
- if self.data_type == "SYSLOG":
141
- fake_message = Events.syslog(count=1, timestamp=self.datetime_obj, observables=self.observables)
142
- if self.data_type == "CEF":
143
- fake_message = Events.cef(count=1, timestamp=self.datetime_obj, vendor=self.vendor,
144
- product=self.product, version=self.version,
145
- observables=self.observables)
146
- if self.data_type == "LEEF":
147
- fake_message = Events.leef(count=1, timestamp=self.datetime_obj, vendor=self.vendor,
148
- product=self.product, version=self.version,
149
- observables=self.observables)
154
+ if self.data_text:
155
+ fake_message = [self.data_text]
156
+ else:
157
+ if self.data_type == "SYSLOG":
158
+ fake_message = Events.syslog(count=1, datetime_iso=self.datetime_obj,
159
+ observables=self.observables, required_fields=self.required_fields)
160
+ if self.data_type == "CEF":
161
+ fake_message = Events.cef(count=1, datetime_iso=self.datetime_obj, vendor=self.vendor,
162
+ product=self.product, version=self.version,
163
+ required_fields=self.required_fields, observables=self.observables)
164
+ if self.data_type == "LEEF":
165
+ fake_message = Events.leef(count=1, datetime_iso=self.datetime_obj, vendor=self.vendor,
166
+ product=self.product, version=self.version,
167
+ required_fields=self.required_fields,
168
+ observables=self.observables)
150
169
  ip_address = self.destination.split(':')[1]
151
170
  port = self.destination.split(':')[2]
152
171
  if 'tcp' in self.destination:
@@ -162,20 +181,29 @@ class Sender:
162
181
  print(f"Worker: {self.worker_name} sending log message to {ip_address} ")
163
182
  sock.sendto(fake_message[0].encode(), (ip_address, int(port)))
164
183
  elif self.data_type in ["JSON", "INCIDENT"]:
165
- if self.data_type == "JSON":
166
- fake_message = Events.json(count=1, timestamp=self.datetime_obj, observables=self.observables)
167
- if self.data_type == "INCIDENT":
168
- fake_message = [{
169
- "alert": Events.incidents(count=1, observables=self.observables, vendor=self.vendor,
170
- version=self.version, product=self.product, fields=self.fields)
171
- }]
184
+ if self.data_json:
185
+ fake_message = [self.data_json]
186
+ else:
187
+ if self.data_type == "JSON":
188
+ fake_message = Events.json(count=1, datetime_iso=self.datetime_obj,
189
+ observables=self.observables, vendor=self.vendor,
190
+ product=self.product, version=self.version,
191
+ required_fields=self.required_fields,)
192
+ if self.data_type == "INCIDENT":
193
+ fake_message = [{
194
+ "alert": Events.incidents(count=1, observables=self.observables, vendor=self.vendor,
195
+ version=self.version, product=self.product,
196
+ datetime_iso=self.datetime_obj,
197
+ required_fields=self.required_fields, fields=self.fields)
198
+ }]
172
199
  if '://' not in self.destination:
173
200
  url = 'http://' + self.destination
174
201
  else:
175
202
  url = self.destination
176
203
  warnings.filterwarnings("ignore", category=InsecureRequestWarning)
177
204
  print(f"Worker: {self.worker_name} sending log message to {url} ")
178
- response = requests.post(url, json=fake_message[0], timeout=(2, 5), verify=self.verify_ssl)
205
+ response = requests.post(url, json=fake_message[0], timeout=(2, 5), headers=self.headers,
206
+ verify=self.verify_ssl)
179
207
  response.raise_for_status()
180
208
  except (ConnectionRefusedError, socket.timeout, requests.exceptions.RequestException) as e:
181
209
  print(f"Connection error: {e}")