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.
- regscale/__init__.py +1 -1
- regscale/core/app/application.py +1 -0
- regscale/core/app/internal/login.py +1 -1
- regscale/core/app/internal/poam_editor.py +1 -1
- regscale/core/app/utils/app_utils.py +1 -1
- regscale/core/app/utils/parser_utils.py +2 -2
- regscale/integrations/commercial/__init__.py +2 -2
- regscale/integrations/commercial/ad.py +1 -1
- regscale/integrations/commercial/azure/intune.py +1 -0
- regscale/integrations/commercial/grype/__init__.py +3 -0
- regscale/integrations/commercial/grype/commands.py +72 -0
- regscale/integrations/commercial/grype/scanner.py +390 -0
- regscale/integrations/commercial/import_all/import_all_cmd.py +2 -2
- regscale/integrations/commercial/nessus/scanner.py +3 -0
- regscale/integrations/commercial/opentext/__init__.py +6 -0
- regscale/integrations/commercial/opentext/commands.py +77 -0
- regscale/integrations/commercial/opentext/scanner.py +449 -85
- regscale/integrations/commercial/sap/sysdig/sysdig_scanner.py +4 -0
- regscale/integrations/commercial/sap/tenable/click.py +1 -1
- regscale/integrations/commercial/sap/tenable/scanner.py +8 -2
- regscale/integrations/commercial/tenablev2/click.py +39 -16
- regscale/integrations/commercial/trivy/__init__.py +5 -0
- regscale/integrations/commercial/trivy/commands.py +74 -0
- regscale/integrations/commercial/trivy/scanner.py +276 -0
- regscale/integrations/commercial/wizv2/click.py +9 -21
- regscale/integrations/commercial/wizv2/scanner.py +2 -1
- regscale/integrations/commercial/wizv2/utils.py +146 -70
- regscale/integrations/jsonl_scanner_integration.py +869 -0
- regscale/integrations/public/fedramp/fedramp_common.py +4 -4
- regscale/integrations/public/fedramp/import_workbook.py +1 -1
- regscale/integrations/public/fedramp/inventory_items.py +3 -3
- regscale/integrations/public/fedramp/poam/scanner.py +51 -44
- regscale/integrations/public/fedramp/ssp_logger.py +6 -6
- regscale/integrations/scanner_integration.py +268 -64
- regscale/models/app_models/mapping.py +3 -3
- regscale/models/integration_models/amazon_models/inspector.py +15 -17
- regscale/models/integration_models/aqua.py +1 -5
- regscale/models/integration_models/cisa_kev_data.json +100 -10
- regscale/models/integration_models/ecr_models/ecr.py +2 -6
- regscale/models/integration_models/{flat_file_importer.py → flat_file_importer/__init__.py} +7 -4
- regscale/models/integration_models/grype_import.py +3 -3
- regscale/models/integration_models/prisma.py +3 -3
- regscale/models/integration_models/synqly_models/capabilities.json +1 -1
- regscale/models/integration_models/synqly_models/connectors/assets.py +1 -0
- regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +2 -0
- regscale/models/integration_models/tenable_models/integration.py +46 -10
- regscale/models/integration_models/trivy_import.py +1 -1
- regscale/models/integration_models/xray.py +1 -1
- regscale/models/regscale_models/__init__.py +2 -0
- regscale/models/regscale_models/control_implementation.py +18 -44
- regscale/models/regscale_models/inherited_control.py +61 -0
- regscale/models/regscale_models/issue.py +3 -2
- regscale/models/regscale_models/mixins/parent_cache.py +1 -1
- regscale/models/regscale_models/regscale_model.py +73 -7
- regscale/models/regscale_models/vulnerability.py +61 -8
- {regscale_cli-6.16.0.0.dist-info → regscale_cli-6.16.2.0.dist-info}/METADATA +3 -3
- {regscale_cli-6.16.0.0.dist-info → regscale_cli-6.16.2.0.dist-info}/RECORD +62 -56
- tests/regscale/core/test_logz.py +8 -0
- regscale/integrations/commercial/grype.py +0 -165
- regscale/integrations/commercial/opentext/click.py +0 -99
- regscale/integrations/commercial/trivy.py +0 -162
- {regscale_cli-6.16.0.0.dist-info → regscale_cli-6.16.2.0.dist-info}/LICENSE +0 -0
- {regscale_cli-6.16.0.0.dist-info → regscale_cli-6.16.2.0.dist-info}/WHEEL +0 -0
- {regscale_cli-6.16.0.0.dist-info → regscale_cli-6.16.2.0.dist-info}/entry_points.txt +0 -0
- {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:
|
|
1881
|
+
def log_controls_info(ssp_obj: SSP, current_imps: List[dict]) -> None:
|
|
1882
1882
|
"""
|
|
1883
1883
|
Log controls info
|
|
1884
1884
|
|
|
1885
|
-
:param
|
|
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="
|
|
2309
|
-
model_layer="
|
|
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 ", ""
|
|
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.
|
|
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.
|
|
209
|
-
logger.info("
|
|
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
|
-
|
|
68
|
+
WEAKNESS_DETECTOR_SOURCE,
|
|
59
69
|
"Weakness Source Identifier",
|
|
60
|
-
|
|
70
|
+
ASSET_IDENTIFIER,
|
|
61
71
|
"Point of Contact",
|
|
62
72
|
"Resources Required",
|
|
63
73
|
"Overall Remediation Plan",
|
|
64
74
|
"Original Detection Date",
|
|
65
|
-
|
|
75
|
+
SCHEDULED_COMPLETION_DATE,
|
|
66
76
|
"Planned Milestones",
|
|
67
|
-
|
|
77
|
+
MILESTONE_CHANGES,
|
|
68
78
|
"Status Date",
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
378
|
-
if val_mapping.get_value(data,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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,
|
|
647
|
-
adjusted_risk_rating = val_mapping.get_value(data,
|
|
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
|
-
|
|
749
|
-
|
|
750
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|