regscale-cli 6.16.0.0__py3-none-any.whl → 6.16.2.0__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 regscale-cli might be problematic. Click here for more details.

Files changed (65) hide show
  1. regscale/__init__.py +1 -1
  2. regscale/core/app/application.py +1 -0
  3. regscale/core/app/internal/login.py +1 -1
  4. regscale/core/app/internal/poam_editor.py +1 -1
  5. regscale/core/app/utils/app_utils.py +1 -1
  6. regscale/core/app/utils/parser_utils.py +2 -2
  7. regscale/integrations/commercial/__init__.py +2 -2
  8. regscale/integrations/commercial/ad.py +1 -1
  9. regscale/integrations/commercial/azure/intune.py +1 -0
  10. regscale/integrations/commercial/grype/__init__.py +3 -0
  11. regscale/integrations/commercial/grype/commands.py +72 -0
  12. regscale/integrations/commercial/grype/scanner.py +390 -0
  13. regscale/integrations/commercial/import_all/import_all_cmd.py +2 -2
  14. regscale/integrations/commercial/nessus/scanner.py +3 -0
  15. regscale/integrations/commercial/opentext/__init__.py +6 -0
  16. regscale/integrations/commercial/opentext/commands.py +77 -0
  17. regscale/integrations/commercial/opentext/scanner.py +449 -85
  18. regscale/integrations/commercial/sap/sysdig/sysdig_scanner.py +4 -0
  19. regscale/integrations/commercial/sap/tenable/click.py +1 -1
  20. regscale/integrations/commercial/sap/tenable/scanner.py +8 -2
  21. regscale/integrations/commercial/tenablev2/click.py +39 -16
  22. regscale/integrations/commercial/trivy/__init__.py +5 -0
  23. regscale/integrations/commercial/trivy/commands.py +74 -0
  24. regscale/integrations/commercial/trivy/scanner.py +276 -0
  25. regscale/integrations/commercial/wizv2/click.py +9 -21
  26. regscale/integrations/commercial/wizv2/scanner.py +2 -1
  27. regscale/integrations/commercial/wizv2/utils.py +146 -70
  28. regscale/integrations/jsonl_scanner_integration.py +869 -0
  29. regscale/integrations/public/fedramp/fedramp_common.py +4 -4
  30. regscale/integrations/public/fedramp/import_workbook.py +1 -1
  31. regscale/integrations/public/fedramp/inventory_items.py +3 -3
  32. regscale/integrations/public/fedramp/poam/scanner.py +51 -44
  33. regscale/integrations/public/fedramp/ssp_logger.py +6 -6
  34. regscale/integrations/scanner_integration.py +268 -64
  35. regscale/models/app_models/mapping.py +3 -3
  36. regscale/models/integration_models/amazon_models/inspector.py +15 -17
  37. regscale/models/integration_models/aqua.py +1 -5
  38. regscale/models/integration_models/cisa_kev_data.json +100 -10
  39. regscale/models/integration_models/ecr_models/ecr.py +2 -6
  40. regscale/models/integration_models/{flat_file_importer.py → flat_file_importer/__init__.py} +7 -4
  41. regscale/models/integration_models/grype_import.py +3 -3
  42. regscale/models/integration_models/prisma.py +3 -3
  43. regscale/models/integration_models/synqly_models/capabilities.json +1 -1
  44. regscale/models/integration_models/synqly_models/connectors/assets.py +1 -0
  45. regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +2 -0
  46. regscale/models/integration_models/tenable_models/integration.py +46 -10
  47. regscale/models/integration_models/trivy_import.py +1 -1
  48. regscale/models/integration_models/xray.py +1 -1
  49. regscale/models/regscale_models/__init__.py +2 -0
  50. regscale/models/regscale_models/control_implementation.py +18 -44
  51. regscale/models/regscale_models/inherited_control.py +61 -0
  52. regscale/models/regscale_models/issue.py +3 -2
  53. regscale/models/regscale_models/mixins/parent_cache.py +1 -1
  54. regscale/models/regscale_models/regscale_model.py +73 -7
  55. regscale/models/regscale_models/vulnerability.py +61 -8
  56. {regscale_cli-6.16.0.0.dist-info → regscale_cli-6.16.2.0.dist-info}/METADATA +3 -3
  57. {regscale_cli-6.16.0.0.dist-info → regscale_cli-6.16.2.0.dist-info}/RECORD +62 -56
  58. tests/regscale/core/test_logz.py +8 -0
  59. regscale/integrations/commercial/grype.py +0 -165
  60. regscale/integrations/commercial/opentext/click.py +0 -99
  61. regscale/integrations/commercial/trivy.py +0 -162
  62. {regscale_cli-6.16.0.0.dist-info → regscale_cli-6.16.2.0.dist-info}/LICENSE +0 -0
  63. {regscale_cli-6.16.0.0.dist-info → regscale_cli-6.16.2.0.dist-info}/WHEEL +0 -0
  64. {regscale_cli-6.16.0.0.dist-info → regscale_cli-6.16.2.0.dist-info}/entry_points.txt +0 -0
  65. {regscale_cli-6.16.0.0.dist-info → regscale_cli-6.16.2.0.dist-info}/top_level.txt +0 -0
@@ -1878,11 +1878,11 @@ def check_control_list_length(ssp_obj: SSP, mapping: dict) -> Optional[list]:
1878
1878
  return missing_controls
1879
1879
 
1880
1880
 
1881
- def log_controls_info(ssp_obj: dict, current_imps: List[dict]) -> None:
1881
+ def log_controls_info(ssp_obj: SSP, current_imps: List[dict]) -> None:
1882
1882
  """
1883
1883
  Log controls info
1884
1884
 
1885
- :param dict ssp_obj: SSP object
1885
+ :param SSP ssp_obj: SSP object
1886
1886
  :param List[dict] current_imps: List of current implementations
1887
1887
  :return None:
1888
1888
  :rtype None:
@@ -2305,8 +2305,8 @@ def fetch_existing_stakeholders(api: Api, config: dict, regscale_ssp: dict) -> l
2305
2305
  if response.ok:
2306
2306
  logger.info(
2307
2307
  f"Found {len(response.json())} existing stakeholders",
2308
- record_type="stackholders",
2309
- model_layer="stackholders",
2308
+ record_type="stakeholders",
2309
+ model_layer="stakeholders",
2310
2310
  )
2311
2311
  return response.json()
2312
2312
  return []
@@ -217,7 +217,7 @@ def map_inventory_to_asset(
217
217
  "ram": 0,
218
218
  "diskStorage": 0,
219
219
  "description": "",
220
- "endOfLifeDate": date_str(mapping.get_value(inventory, "End-of-Life ", "", warnings=False)),
220
+ "endOfLifeDate": date_str(mapping.get_value(inventory, "End-of-Life ", "")),
221
221
  "purchaseDate": None,
222
222
  "status": "Active (On Network)",
223
223
  "wizId": "",
@@ -59,7 +59,7 @@ def get_dict_value(outer_key: str, inner_key: str, source_dict: Dict) -> Optiona
59
59
  outer_dict = source_dict.get(outer_key, None)
60
60
  if outer_dict is not None and isinstance(outer_dict, dict):
61
61
  val = outer_dict.get(inner_key, None)
62
- logger.info(f"{val}")
62
+ logger.debug(f"{val=}")
63
63
  return val
64
64
  return None
65
65
 
@@ -205,8 +205,8 @@ def parse_inventory_items(trv: FedrampTraversal, components_dict: Dict):
205
205
 
206
206
  for imp_component in implemented_components:
207
207
  if not isinstance(components_dict, dict):
208
- logger.info(components_dict)
209
- logger.info("components do not exist yet")
208
+ logger.debug(components_dict)
209
+ logger.info("Components do not exist yet.")
210
210
  continue
211
211
  comp = components_dict.get(imp_component.get("component_uuid"))
212
212
  comp_id = comp.get("id") if comp else None
@@ -4,7 +4,10 @@
4
4
 
5
5
  import logging
6
6
  import re
7
- from typing import Iterator, List, Optional
7
+ from typing import Iterator, List, Optional, TYPE_CHECKING
8
+
9
+ if TYPE_CHECKING:
10
+ import numpy
8
11
 
9
12
  from openpyxl import load_workbook # type: ignore
10
13
  from openpyxl.utils import column_index_from_string # type: ignore
@@ -25,6 +28,14 @@ from regscale.validation.address import validate_ip_address, validate_mac_addres
25
28
 
26
29
  logger = logging.getLogger("regscale")
27
30
 
31
+ WEAKNESS_DETECTOR_SOURCE = "Weakness Detector Source"
32
+ ASSET_IDENTIFIER = "Asset Identifier"
33
+ SCHEDULED_COMPLETION_DATE = "Scheduled Completion Date"
34
+ MILESTONE_CHANGES = "Milestone Changes"
35
+ ORIGINAL_RISK_RATING = "Original Risk Rating"
36
+ ADJUSTED_RISK_RATING = "Adjusted Risk Rating"
37
+ FILE_PATH_ERROR = "File path is required."
38
+
28
39
 
29
40
  class FedrampPoamIntegration(ScannerIntegration):
30
41
  """Integration class for FedRAMP POAM scanning."""
@@ -50,40 +61,43 @@ class FedrampPoamIntegration(ScannerIntegration):
50
61
  skipped_records: int = 0
51
62
  processed_assets: set[str] = set() # Track processed assets across all methods
52
63
 
53
- # TODO: Pair this down to only usable data
54
64
  fedramp_poam_columns = [
55
65
  "POAM ID",
56
66
  "Weakness Name",
57
67
  "Weakness Description",
58
- "Weakness Detector Source",
68
+ WEAKNESS_DETECTOR_SOURCE,
59
69
  "Weakness Source Identifier",
60
- "Asset Identifier",
70
+ ASSET_IDENTIFIER,
61
71
  "Point of Contact",
62
72
  "Resources Required",
63
73
  "Overall Remediation Plan",
64
74
  "Original Detection Date",
65
- "Scheduled Completion Date",
75
+ SCHEDULED_COMPLETION_DATE,
66
76
  "Planned Milestones",
67
- "Milestone Changes",
77
+ MILESTONE_CHANGES,
68
78
  "Status Date",
69
- # "Vendor Dependency",
70
- # "Last Vendor Check-in Date",
71
- # "Vendor Dependent Product Name",
72
- "Original Risk Rating",
73
- "Adjusted Risk Rating",
79
+ ORIGINAL_RISK_RATING,
80
+ ADJUSTED_RISK_RATING,
74
81
  "Risk Adjustment",
75
82
  "False Positive",
76
83
  "Operational Requirement",
77
84
  "Deviation Rationale",
78
- # "Supporting Documents",
79
85
  "Comments",
80
- # "Auto-Approve",
81
- # "Binding Operational Directive 22-01 tracking",
82
- # "Binding Operational Directive 22-01 Due Date",
83
- # "CVE",
84
- # "Service Name",
85
86
  ]
86
87
 
88
+ """
89
+ Unused columns:
90
+ # "Vendor Dependency",
91
+ # "Last Vendor Check-in Date",
92
+ # "Vendor Dependent Product Name",
93
+ # "Supporting Documents",
94
+ # "Auto-Approve",
95
+ # "Binding Operational Directive 22-01 tracking",
96
+ # "Binding Operational Directive 22-01 Due Date",
97
+ # "CVE",
98
+ # "Service Name",
99
+ """
100
+
87
101
  def __init__(self, plan_id: int, **kwargs: dict):
88
102
  super().__init__(plan_id=plan_id)
89
103
  try:
@@ -91,7 +105,7 @@ class FedrampPoamIntegration(ScannerIntegration):
91
105
  if "file_path" in kwargs:
92
106
  self.file_path = kwargs["file_path"]
93
107
  if not self.file_path:
94
- raise ValueError("File path is required")
108
+ error_and_exit(FILE_PATH_ERROR)
95
109
  self.workbook = self.workbook or load_workbook(filename=self.file_path, data_only=True, read_only=True)
96
110
  self.poam_sheets = kwargs.get("poam_sheets") or [
97
111
  sheet for sheet in self.workbook.sheetnames if re.search("POA&M Items", sheet)
@@ -130,11 +144,10 @@ class FedrampPoamIntegration(ScannerIntegration):
130
144
  """
131
145
  Fetches findings from FedRAMP POAM files.
132
146
 
133
- :raises ValueError: If file path is not set
134
147
  :yield: Iterator of validated integration findings
135
148
  """
136
149
  if not self.file_path:
137
- raise ValueError("File path is required")
150
+ error_and_exit(FILE_PATH_ERROR)
138
151
 
139
152
  findings = []
140
153
  try:
@@ -256,7 +269,7 @@ class FedrampPoamIntegration(ScannerIntegration):
256
269
  "critical": IssueSeverity.High.name,
257
270
  "low": IssueSeverity.Low.name,
258
271
  }
259
- res = validator.mapping.get_value(data, "Original Risk Rating")
272
+ res = validator.mapping.get_value(data, ORIGINAL_RISK_RATING)
260
273
  if res.lower() not in [mem.lower() for mem in IssueSeverity.__members__]:
261
274
  res = dat_map.get(res.lower(), IssueSeverity.Low.name)
262
275
  return res
@@ -345,7 +358,7 @@ class FedrampPoamIntegration(ScannerIntegration):
345
358
  plugin_id_int = abs(hash(poam_id)) % (10**9)
346
359
 
347
360
  # Get asset identifiers
348
- asset_ids = val_mapping.get_value(data, "Asset Identifier")
361
+ asset_ids = val_mapping.get_value(data, ASSET_IDENTIFIER)
349
362
  if not asset_ids:
350
363
  logger.warning(f"No asset identifier found on row {index}, sheet {sheet}. Skipping.")
351
364
  yield from findings
@@ -374,8 +387,8 @@ class FedrampPoamIntegration(ScannerIntegration):
374
387
  date_str(val_mapping.get_value(data, "Original Detection Date")) or get_current_datetime()
375
388
  )
376
389
  due_date = date_str(
377
- val_mapping.get_value(data, "Scheduled Completion Date")
378
- if val_mapping.get_value(data, "Scheduled Completion Date") != "#REF!"
390
+ val_mapping.get_value(data, SCHEDULED_COMPLETION_DATE)
391
+ if val_mapping.get_value(data, SCHEDULED_COMPLETION_DATE) != "#REF!"
379
392
  else ""
380
393
  )
381
394
  severity: IssueSeverity = getattr(IssueSeverity, category.title(), IssueSeverity.NotAssigned)
@@ -408,18 +421,18 @@ class FedrampPoamIntegration(ScannerIntegration):
408
421
  date_last_updated=status_date,
409
422
  due_date=due_date,
410
423
  cve=cve, # Single CVE per finding
411
- plugin_name=val_mapping.get_value(data, "Weakness Detector Source") or "",
424
+ plugin_name=val_mapping.get_value(data, WEAKNESS_DETECTOR_SOURCE) or "",
412
425
  plugin_id=str(unique_plugin_id),
413
- observations=str(val_mapping.get_value(data, "Milestone Changes")) or "",
426
+ observations=str(val_mapping.get_value(data, MILESTONE_CHANGES)) or "",
414
427
  poam_comments=self.empty(val_mapping.get_value(data, "Comments")),
415
428
  remediation=self.empty(val_mapping.get_value(data, "Overall Remediation Plan")),
416
429
  basis_for_adjustment=str(self.get_basis_for_adjustment(val_mapping=val_mapping, data=data)),
417
430
  vulnerability_type="FedRAMP",
418
- source_report=str(val_mapping.get_value(data, "Weakness Detector Source")),
431
+ source_report=str(val_mapping.get_value(data, WEAKNESS_DETECTOR_SOURCE)),
419
432
  point_of_contact=str(val_mapping.get_value(data, "Point of Contact")),
420
- milestone_changes=str(val_mapping.get_value(data, "Milestone Changes")),
433
+ milestone_changes=str(val_mapping.get_value(data, MILESTONE_CHANGES)),
421
434
  planned_milestone_changes=str(val_mapping.get_value(data, "Planned Milestones")),
422
- adjusted_risk_rating=val_mapping.get_value(data, "Adjusted Risk Rating"),
435
+ adjusted_risk_rating=val_mapping.get_value(data, ADJUSTED_RISK_RATING),
423
436
  risk_adjustment=self.determine_risk_adjustment(val_mapping.get_value(data, "Risk Adjustment")),
424
437
  operational_requirements=str(val_mapping.get_value(data, "Operational Requirement")),
425
438
  deviation_rationale=str(val_mapping.get_value(data, "Deviation Rationale")),
@@ -452,7 +465,7 @@ class FedrampPoamIntegration(ScannerIntegration):
452
465
  res = date_str(status_map.get(resolve_status), "%m-%d-%Y")
453
466
  if res:
454
467
  logger.warning(
455
- f"Status Date missing on row %i, sheet %s, defaulting to %s: %s",
468
+ "Status Date missing on row %i, sheet %s, defaulting to %s: %s",
456
469
  index,
457
470
  sheet,
458
471
  resolve_status.lower().replace("_", " "),
@@ -482,7 +495,7 @@ class FedrampPoamIntegration(ScannerIntegration):
482
495
  else:
483
496
  logger.error("Validator mapping is None")
484
497
  return row_assets
485
- asset_ids = val_mapping.get_value(data, "Asset Identifier")
498
+ asset_ids = val_mapping.get_value(data, ASSET_IDENTIFIER)
486
499
  if not asset_ids:
487
500
  return row_assets
488
501
  asset_id_list = self.gen_asset_list(asset_ids)
@@ -643,8 +656,8 @@ class FedrampPoamIntegration(ScannerIntegration):
643
656
  :rtype: Optional[str]
644
657
  """
645
658
  basis_for_adjustment = self.empty(val_mapping.get_value(data, "Comments")) # e.g. row 23
646
- risk_rating = val_mapping.get_value(data, "Original Risk Rating")
647
- adjusted_risk_rating = val_mapping.get_value(data, "Adjusted Risk Rating")
659
+ risk_rating = val_mapping.get_value(data, ORIGINAL_RISK_RATING)
660
+ adjusted_risk_rating = val_mapping.get_value(data, ADJUSTED_RISK_RATING)
648
661
 
649
662
  if (adjusted_risk_rating != risk_rating) and not basis_for_adjustment:
650
663
  return "POAM Import"
@@ -745,19 +758,12 @@ class FedrampPoamIntegration(ScannerIntegration):
745
758
  """
746
759
  Fetch assets from FedRAMP POAM files.
747
760
 
748
- Args:
749
- *args: Variable length argument list
750
- **kwargs: Arbitrary keyword arguments
751
-
752
- Returns:
753
- Iterator[IntegrationAsset]: Iterator of parsed integration assets
754
-
755
- Raises:
756
- ValueError: If file_path is not set
757
- POAMProcessingError: If there's an error processing the POAM file
761
+ :raises POAMProcessingError: If there's an error processing the POAM file
762
+ :return: Iterator of parsed integration assets
763
+ :rtype: Iterator[IntegrationAsset]
758
764
  """
759
765
  if not self.file_path:
760
- raise ValueError("File path is required")
766
+ error_and_exit(FILE_PATH_ERROR)
761
767
 
762
768
  assets = []
763
769
  total_processed = 0
@@ -808,6 +814,7 @@ class FedrampPoamIntegration(ScannerIntegration):
808
814
  finally:
809
815
  logger.info(f"Completed processing with {total_processed} assets and {self.error_records} errors")
810
816
 
817
+ self.num_assets_to_process = len(assets)
811
818
  return iter(assets)
812
819
 
813
820
  def find_max_row(self, start_row: int, ws: Worksheet) -> int:
@@ -8,23 +8,22 @@ import logging
8
8
  from regscale.core.app.logz import create_logger
9
9
 
10
10
 
11
- class CaptureEventsHandler:
11
+ class CaptureEventsHandler(logging.Handler):
12
12
  def __init__(self, events, errors, infos):
13
- self.handler = logging.Handler()
14
13
  self.events = events
15
14
  self.errors = errors
16
15
  self.infos = infos
16
+ super().__init__()
17
17
 
18
18
  def emit(self, record):
19
- self.handler.emit(record)
20
19
  try:
21
- log_entry = self.handler.format(record)
20
+ log_entry = self.format(record)
22
21
  if record.levelname == "INFO":
23
22
  self.events.append(log_entry)
24
23
  elif record.levelname == "ERROR":
25
24
  self.errors.append(log_entry)
26
25
  except Exception:
27
- self.handler.handleError(record)
26
+ self.handleError(record)
28
27
 
29
28
 
30
29
  class SSPLogger:
@@ -33,7 +32,8 @@ class SSPLogger:
33
32
  self.errors = []
34
33
  self.infos = []
35
34
  self.capture_handler = CaptureEventsHandler(self.events, self.errors, self.infos)
36
- self.logger = create_logger(custom_handler=self.capture_handler)
35
+ logger = create_logger(custom_handler=self.capture_handler)
36
+ self.logger = logger
37
37
 
38
38
  def create_logger(self):
39
39
  return self.logger