regscale-cli 6.21.2.0__py3-none-any.whl → 6.21.2.2__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/_version.py +1 -1
- regscale/core/app/application.py +1 -0
- regscale/integrations/commercial/wizv2/policy_compliance.py +105 -37
- regscale/integrations/compliance_integration.py +6 -6
- regscale/integrations/scanner_integration.py +6 -6
- regscale/models/integration_models/cisa_kev_data.json +49 -3
- regscale/models/regscale_models/milestone.py +32 -14
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.21.2.2.dist-info}/METADATA +1 -1
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.21.2.2.dist-info}/RECORD +13 -13
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.21.2.2.dist-info}/LICENSE +0 -0
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.21.2.2.dist-info}/WHEEL +0 -0
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.21.2.2.dist-info}/entry_points.txt +0 -0
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.21.2.2.dist-info}/top_level.txt +0 -0
regscale/_version.py
CHANGED
regscale/core/app/application.py
CHANGED
|
@@ -260,6 +260,7 @@ class Application(metaclass=Singleton):
|
|
|
260
260
|
"tenableMinimumSeverityFilter": "low",
|
|
261
261
|
"token": DEFAULT_POPULATED,
|
|
262
262
|
"userId": "enter RegScale user id here",
|
|
263
|
+
"useMilestones": False,
|
|
263
264
|
"otx": "enter AlienVault API key here",
|
|
264
265
|
"wizAccessToken": DEFAULT_POPULATED,
|
|
265
266
|
"wizAuthUrl": "https://auth.wiz.io/oauth/token",
|
|
@@ -39,6 +39,7 @@ from regscale.integrations.scanner_integration import (
|
|
|
39
39
|
IntegrationFinding,
|
|
40
40
|
issue_due_date,
|
|
41
41
|
)
|
|
42
|
+
from regscale.integrations.variables import ScannerVariables
|
|
42
43
|
from regscale.models import regscale_models
|
|
43
44
|
|
|
44
45
|
logger = logging.getLogger("regscale")
|
|
@@ -193,6 +194,8 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
193
194
|
type = ScannerIntegrationType.CONTROL_TEST
|
|
194
195
|
# Use wizId field for asset identification (matches other Wiz integrations)
|
|
195
196
|
asset_identifier_field = "wizId"
|
|
197
|
+
issue_identifier_field = "wizId"
|
|
198
|
+
|
|
196
199
|
# Do not create assets - they come from separate inventory import
|
|
197
200
|
options_map_assets_to_components: bool = False
|
|
198
201
|
# Do not create vulnerabilities from compliance policy results
|
|
@@ -906,7 +909,7 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
906
909
|
|
|
907
910
|
asset = IntegrationAsset(
|
|
908
911
|
name=compliance_item.resource_name,
|
|
909
|
-
identifier=
|
|
912
|
+
identifier=compliance_item.resource_name, # Use name only without UUID
|
|
910
913
|
external_id=compliance_item.resource_id,
|
|
911
914
|
other_tracking_number=compliance_item.resource_id, # For deduplication
|
|
912
915
|
asset_type=asset_type,
|
|
@@ -1239,7 +1242,7 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
1239
1242
|
filtered_nodes = self._filter_nodes_to_framework(nodes)
|
|
1240
1243
|
progress.update(
|
|
1241
1244
|
task,
|
|
1242
|
-
description=f"[green]
|
|
1245
|
+
description=f"[green]Completed Wiz policy assessments: {len(filtered_nodes)} nodes",
|
|
1243
1246
|
completed=1,
|
|
1244
1247
|
total=1,
|
|
1245
1248
|
)
|
|
@@ -1816,19 +1819,19 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
1816
1819
|
self._sync_assets()
|
|
1817
1820
|
|
|
1818
1821
|
# Step 2: CRITICAL - Pre-populate control implementation cache BEFORE creating assessments
|
|
1819
|
-
logger.info("
|
|
1822
|
+
logger.info("Pre-populating control implementation cache for issue processing...")
|
|
1820
1823
|
self._populate_control_implementation_cache()
|
|
1821
1824
|
|
|
1822
1825
|
# Step 3: Create control assessments BEFORE issues (ensures assessmentId is available)
|
|
1823
|
-
logger.info("
|
|
1826
|
+
logger.info("Creating control assessments BEFORE issue processing...")
|
|
1824
1827
|
self._sync_control_assessments()
|
|
1825
1828
|
|
|
1826
1829
|
# Step 3.5: CRITICAL - Refresh assessment cache after assessments are created
|
|
1827
|
-
logger.info("
|
|
1830
|
+
logger.info("Refreshing assessment cache with newly created assessments...")
|
|
1828
1831
|
self._refresh_assessment_cache_after_creation()
|
|
1829
1832
|
|
|
1830
1833
|
# Step 4: NOW process issues with controlId and assessmentId properly set
|
|
1831
|
-
logger.info("
|
|
1834
|
+
logger.info("Processing issues with control and assessment IDs available...")
|
|
1832
1835
|
self._sync_issues()
|
|
1833
1836
|
|
|
1834
1837
|
self._finalize_scan_history(scan_history)
|
|
@@ -1868,7 +1871,7 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
1868
1871
|
|
|
1869
1872
|
# Step 3: Sync using the overridden method (which ensures proper ordering)
|
|
1870
1873
|
logger.info(
|
|
1871
|
-
f"
|
|
1874
|
+
f"Sync parameters: create_issues={self.create_issues}, update_control_status={self.update_control_status}"
|
|
1872
1875
|
)
|
|
1873
1876
|
|
|
1874
1877
|
self.sync_compliance()
|
|
@@ -1932,7 +1935,7 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
1932
1935
|
# CRITICAL FIX: If assessment_id is set, prepare the finding for assessment parenting
|
|
1933
1936
|
if hasattr(finding, "assessment_id") and finding.assessment_id:
|
|
1934
1937
|
assessment_id = finding.assessment_id
|
|
1935
|
-
logger.debug(f"
|
|
1938
|
+
logger.debug(f"PRE-SETTING ASSESSMENT PARENT: assessmentId={assessment_id}")
|
|
1936
1939
|
|
|
1937
1940
|
# Add parent override fields to the finding for the ScannerIntegration to use
|
|
1938
1941
|
finding._override_parent_id = assessment_id
|
|
@@ -2031,7 +2034,7 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2031
2034
|
if hasattr(finding, "_override_parent_id") and hasattr(finding, "_override_parent_module"):
|
|
2032
2035
|
parent_id = finding._override_parent_id
|
|
2033
2036
|
parent_module = finding._override_parent_module
|
|
2034
|
-
logger.debug(f"
|
|
2037
|
+
logger.debug(f"USING OVERRIDE PARENT: {parent_module} #{parent_id}")
|
|
2035
2038
|
else:
|
|
2036
2039
|
parent_id = self.plan_id
|
|
2037
2040
|
parent_module = self.parent_module
|
|
@@ -2084,7 +2087,7 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2084
2087
|
|
|
2085
2088
|
# CRITICAL: Set assessmentId (this is the key fix)
|
|
2086
2089
|
issue.assessmentId = finding.assessment_id
|
|
2087
|
-
logger.debug(f"
|
|
2090
|
+
logger.debug(f"SETTING assessmentId = {finding.assessment_id} with parent = {parent_module} #{parent_id}")
|
|
2088
2091
|
|
|
2089
2092
|
control_id = self.get_control_implementation_id_for_cci(finding.cci_ref) if finding.cci_ref else None
|
|
2090
2093
|
issue.controlId = control_id
|
|
@@ -2117,16 +2120,30 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2117
2120
|
issue = self.lookup_kev_and_update_issue(cve=finding.cve, issue=issue, cisa_kevs=self._kev_data)
|
|
2118
2121
|
|
|
2119
2122
|
if existing_issue:
|
|
2120
|
-
logger.debug(f"
|
|
2123
|
+
logger.debug(f"Saving existing issue {issue.id} with assessmentId={issue.assessmentId}")
|
|
2121
2124
|
issue.save(bulk=True)
|
|
2122
2125
|
else:
|
|
2123
|
-
logger.info(f"
|
|
2126
|
+
logger.info(f"Creating new issue with assessmentId={issue.assessmentId}")
|
|
2124
2127
|
issue = issue.create_or_update(
|
|
2125
2128
|
bulk_update=True, defaults={"otherIdentifier": self._get_other_identifier(finding, is_poam)}
|
|
2126
2129
|
)
|
|
2127
|
-
|
|
2130
|
+
if issue and issue.id:
|
|
2131
|
+
logger.debug(f"Issue created with ID: {issue.id}")
|
|
2132
|
+
self.extra_data_to_properties(finding, issue.id)
|
|
2133
|
+
else:
|
|
2134
|
+
logger.error(f" Issue creation failed - no ID returned for finding {finding.external_id}")
|
|
2135
|
+
return None
|
|
2136
|
+
|
|
2137
|
+
# Only create milestones if issue has an ID
|
|
2138
|
+
if issue and issue.id:
|
|
2139
|
+
# Check if existing issue needs initial milestone creation
|
|
2140
|
+
if existing_issue and ScannerVariables.useMilestones:
|
|
2141
|
+
self._ensure_issue_has_milestone(issue, finding)
|
|
2142
|
+
|
|
2143
|
+
self._handle_property_and_milestone_creation(issue, finding, existing_issue)
|
|
2144
|
+
else:
|
|
2145
|
+
logger.debug("Skipping milestone creation - issue has no ID")
|
|
2128
2146
|
|
|
2129
|
-
self._handle_property_and_milestone_creation(issue, finding, existing_issue)
|
|
2130
2147
|
return issue
|
|
2131
2148
|
|
|
2132
2149
|
def _populate_compliance_fields_on_finding(self, finding: IntegrationFinding) -> None:
|
|
@@ -2163,6 +2180,59 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2163
2180
|
except Exception:
|
|
2164
2181
|
pass
|
|
2165
2182
|
|
|
2183
|
+
def _ensure_issue_has_milestone(self, issue: regscale_models.Issue, finding: IntegrationFinding) -> None:
|
|
2184
|
+
"""
|
|
2185
|
+
Ensure that an existing issue has at least one milestone.
|
|
2186
|
+
|
|
2187
|
+
This method checks if an existing issue has any milestones, and if not,
|
|
2188
|
+
creates an initial "Issue created" milestone. This handles cases where
|
|
2189
|
+
issues were created before milestone tracking was enabled, or were
|
|
2190
|
+
created through other means without milestones.
|
|
2191
|
+
|
|
2192
|
+
:param issue: The existing issue to check for milestones
|
|
2193
|
+
:param finding: The finding data
|
|
2194
|
+
:return: None
|
|
2195
|
+
"""
|
|
2196
|
+
try:
|
|
2197
|
+
# Check if the issue already has milestones
|
|
2198
|
+
# We need to make a direct API call because the Milestone model's endpoint configuration
|
|
2199
|
+
# doesn't include the module parameter that the API expects
|
|
2200
|
+
from regscale.models.regscale_models.milestone import Milestone
|
|
2201
|
+
|
|
2202
|
+
try:
|
|
2203
|
+
existing_milestones = Milestone.get_all_by_parent(parent_id=issue.id, parent_module="issues")
|
|
2204
|
+
logger.debug(f"Fetched {len(existing_milestones)} existing milestones for issue {issue.id}")
|
|
2205
|
+
except Exception as api_error:
|
|
2206
|
+
# If the API call fails, log it and assume no milestones exist
|
|
2207
|
+
logger.debug(f"Could not fetch existing milestones for issue {issue.id}: {api_error}")
|
|
2208
|
+
existing_milestones = []
|
|
2209
|
+
|
|
2210
|
+
if not existing_milestones:
|
|
2211
|
+
# Create an initial milestone for the existing issue
|
|
2212
|
+
logger.debug(f"Creating initial milestone for existing issue {issue.id} that had no milestones")
|
|
2213
|
+
|
|
2214
|
+
# Use the issue's dateCreated if available, otherwise use current date
|
|
2215
|
+
if hasattr(issue, "dateCreated") and issue.dateCreated:
|
|
2216
|
+
# Convert to string if it's a datetime object (e.g., in tests)
|
|
2217
|
+
if hasattr(issue.dateCreated, "isoformat"):
|
|
2218
|
+
milestone_date = issue.dateCreated.isoformat()
|
|
2219
|
+
else:
|
|
2220
|
+
milestone_date = issue.dateCreated
|
|
2221
|
+
else:
|
|
2222
|
+
milestone_date = get_current_datetime()
|
|
2223
|
+
|
|
2224
|
+
regscale_models.Milestone(
|
|
2225
|
+
title=f"Issue created by {self.title}",
|
|
2226
|
+
milestoneDate=milestone_date,
|
|
2227
|
+
responsiblePersonId=self.assessor_id,
|
|
2228
|
+
parentID=issue.id,
|
|
2229
|
+
parentModule=regscale_models.Issue.get_module_slug(),
|
|
2230
|
+
).create()
|
|
2231
|
+
|
|
2232
|
+
logger.debug(f"Created initial milestone for existing issue {issue.id}")
|
|
2233
|
+
except Exception as e:
|
|
2234
|
+
logger.warning(f"Could not check/create milestone for issue {issue.id}: {e}")
|
|
2235
|
+
|
|
2166
2236
|
def _enhance_issue_with_compliance_fields(self, issue: regscale_models.Issue, finding: IntegrationFinding) -> None:
|
|
2167
2237
|
"""
|
|
2168
2238
|
Enhance an issue with compliance-specific fields (controlId and assessmentId).
|
|
@@ -2231,7 +2301,7 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2231
2301
|
try:
|
|
2232
2302
|
from regscale.models import regscale_models
|
|
2233
2303
|
|
|
2234
|
-
logger.info("
|
|
2304
|
+
logger.info("Pre-populating control implementation cache for issue processing...")
|
|
2235
2305
|
|
|
2236
2306
|
# Get all control implementations for this plan
|
|
2237
2307
|
implementations = regscale_models.ControlImplementation.get_all_by_parent(
|
|
@@ -2285,7 +2355,7 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2285
2355
|
except Exception:
|
|
2286
2356
|
continue
|
|
2287
2357
|
|
|
2288
|
-
logger.info("
|
|
2358
|
+
logger.info("Control implementation cache populated:")
|
|
2289
2359
|
logger.info(f" - {controls_mapped} control ID mappings")
|
|
2290
2360
|
logger.info(f" - {assessments_mapped} assessment mappings")
|
|
2291
2361
|
|
|
@@ -2307,7 +2377,7 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2307
2377
|
from regscale.models import regscale_models
|
|
2308
2378
|
from datetime import datetime
|
|
2309
2379
|
|
|
2310
|
-
logger.info("
|
|
2380
|
+
logger.info("Refreshing assessment cache with newly created assessments...")
|
|
2311
2381
|
|
|
2312
2382
|
refreshed_count = 0
|
|
2313
2383
|
today = datetime.now().date()
|
|
@@ -2361,7 +2431,7 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2361
2431
|
except Exception:
|
|
2362
2432
|
continue
|
|
2363
2433
|
|
|
2364
|
-
logger.info(f"
|
|
2434
|
+
logger.info(f"Assessment cache refreshed: {refreshed_count} assessments updated")
|
|
2365
2435
|
|
|
2366
2436
|
except Exception as e:
|
|
2367
2437
|
logger.error(f"Error refreshing assessment cache: {e}")
|
|
@@ -2408,7 +2478,7 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2408
2478
|
impl_control_id = self._normalize_control_id_string(security_control.controlId)
|
|
2409
2479
|
|
|
2410
2480
|
if impl_control_id == control_id:
|
|
2411
|
-
logger.info(f"
|
|
2481
|
+
logger.info(f"Found control implementation {impl.id} for control {control_id}")
|
|
2412
2482
|
# Cache it for future lookups
|
|
2413
2483
|
if not hasattr(self, "_impl_id_by_control"):
|
|
2414
2484
|
self._impl_id_by_control = {}
|
|
@@ -2418,7 +2488,7 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2418
2488
|
continue
|
|
2419
2489
|
|
|
2420
2490
|
logger.warning(
|
|
2421
|
-
f"
|
|
2491
|
+
f"No control implementation found for control {control_id} among {len(implementations)} implementations"
|
|
2422
2492
|
)
|
|
2423
2493
|
return None
|
|
2424
2494
|
except Exception as e:
|
|
@@ -2495,9 +2565,7 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2495
2565
|
# Sort by ID (highest/newest first) if multiple today
|
|
2496
2566
|
today_assessments.sort(key=lambda a: a.id if hasattr(a, "id") else 0, reverse=True)
|
|
2497
2567
|
assessment = today_assessments[0]
|
|
2498
|
-
logger.info(
|
|
2499
|
-
f"✓ Found today's assessment {assessment.id} for control implementation {implementation_id}"
|
|
2500
|
-
)
|
|
2568
|
+
logger.info(f"Found today's assessment {assessment.id} for control implementation {implementation_id}")
|
|
2501
2569
|
# Cache it for future lookups
|
|
2502
2570
|
if not hasattr(self, "_assessment_by_impl_today"):
|
|
2503
2571
|
self._assessment_by_impl_today = {}
|
|
@@ -2512,14 +2580,14 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2512
2580
|
reverse=True,
|
|
2513
2581
|
)
|
|
2514
2582
|
assessment = recent_assessments[0][0]
|
|
2515
|
-
logger.info(f"
|
|
2583
|
+
logger.info(f"Found recent assessment {assessment.id} for control implementation {implementation_id}")
|
|
2516
2584
|
# Cache it even if not today's
|
|
2517
2585
|
if not hasattr(self, "_assessment_by_impl_today"):
|
|
2518
2586
|
self._assessment_by_impl_today = {}
|
|
2519
2587
|
self._assessment_by_impl_today[implementation_id] = assessment
|
|
2520
2588
|
return assessment.id
|
|
2521
2589
|
|
|
2522
|
-
logger.warning(f"
|
|
2590
|
+
logger.warning(f"No usable assessments found for control implementation {implementation_id}")
|
|
2523
2591
|
return None
|
|
2524
2592
|
except Exception as e:
|
|
2525
2593
|
logger.error(f"Error finding assessment for control implementation {implementation_id}: {e}")
|
|
@@ -2558,7 +2626,7 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2558
2626
|
with existing assets in RegScale. This ensures we don't create assessments for
|
|
2559
2627
|
controls that have no assets in our boundary.
|
|
2560
2628
|
"""
|
|
2561
|
-
logger.info("
|
|
2629
|
+
logger.info("Starting control assessment processing for Wiz compliance integration")
|
|
2562
2630
|
|
|
2563
2631
|
# Ensure existing records cache is loaded
|
|
2564
2632
|
self._load_existing_records_cache()
|
|
@@ -2615,8 +2683,8 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2615
2683
|
validated_passing_controls[control_id] = self.passing_controls[control_id]
|
|
2616
2684
|
|
|
2617
2685
|
if not validated_controls_with_assets:
|
|
2618
|
-
logger.warning("
|
|
2619
|
-
logger.info("
|
|
2686
|
+
logger.warning(" No controls have assets in RegScale boundary - no control assessments will be created")
|
|
2687
|
+
logger.info("SUMMARY: 0 control assessments created (no assets exist in RegScale)")
|
|
2620
2688
|
return
|
|
2621
2689
|
|
|
2622
2690
|
assessments_created = 0
|
|
@@ -2638,15 +2706,15 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2638
2706
|
|
|
2639
2707
|
if assessments_created > 0:
|
|
2640
2708
|
logger.info(
|
|
2641
|
-
f"
|
|
2709
|
+
f"Created {assessments_created} control assessments: {passing_assessments} passing, {failing_assessments} failing"
|
|
2642
2710
|
)
|
|
2643
2711
|
else:
|
|
2644
2712
|
logger.warning(
|
|
2645
|
-
f"
|
|
2713
|
+
f"No control assessments were actually created (0 assessments) despite finding {len(validated_controls_with_assets)} controls with assets"
|
|
2646
2714
|
)
|
|
2647
2715
|
|
|
2648
2716
|
logger.info(
|
|
2649
|
-
f"
|
|
2717
|
+
f"CONTROL ASSESSMENT SUMMARY: {assessments_created} assessments created for {len(validated_controls_with_assets)} validated controls"
|
|
2650
2718
|
)
|
|
2651
2719
|
|
|
2652
2720
|
def _sync_assessment_cache_from_base_class(self) -> None:
|
|
@@ -2665,10 +2733,10 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2665
2733
|
self._control_cache.set_assessment(impl_id, assessment)
|
|
2666
2734
|
synced_count += 1
|
|
2667
2735
|
|
|
2668
|
-
logger.info(f"
|
|
2736
|
+
logger.info(f"Synced {synced_count} assessments from base class cache to control cache")
|
|
2669
2737
|
|
|
2670
2738
|
except Exception as e:
|
|
2671
|
-
logger.warning(f"
|
|
2739
|
+
logger.warning(f"Failed to sync assessment cache: {e}")
|
|
2672
2740
|
|
|
2673
2741
|
def _get_validated_control_compliance_items(self, control_id: str) -> List[ComplianceItem]:
|
|
2674
2742
|
"""
|
|
@@ -2861,7 +2929,7 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2861
2929
|
self._load_existing_records_cache()
|
|
2862
2930
|
|
|
2863
2931
|
# CRITICAL: Pre-populate control implementation cache before any processing
|
|
2864
|
-
logger.info("
|
|
2932
|
+
logger.info("Pre-populating control implementation cache for reliable issue linking...")
|
|
2865
2933
|
self._populate_control_implementation_cache()
|
|
2866
2934
|
|
|
2867
2935
|
# Call parent's compliance data processing (assessments, etc.) but skip issue creation
|
|
@@ -2891,10 +2959,10 @@ class WizPolicyComplianceIntegration(ComplianceIntegration):
|
|
|
2891
2959
|
)
|
|
2892
2960
|
|
|
2893
2961
|
logger.info(
|
|
2894
|
-
f"
|
|
2962
|
+
f"SUMMARY: Processed {issues_processed} policy violations resulting in {actual_issues} consolidated issues for failed controls for assets in RegScale"
|
|
2895
2963
|
)
|
|
2896
2964
|
else:
|
|
2897
|
-
logger.info("
|
|
2965
|
+
logger.info("SUMMARY: No issues processed - no failed controls with existing assets")
|
|
2898
2966
|
|
|
2899
2967
|
except Exception as e:
|
|
2900
2968
|
error_and_exit(f"Error during Wiz compliance sync: {e}")
|
|
@@ -3017,7 +3085,7 @@ def list_available_frameworks() -> str:
|
|
|
3017
3085
|
output.append("=" * 50)
|
|
3018
3086
|
|
|
3019
3087
|
# Show shorthand mappings first
|
|
3020
|
-
output.append("\
|
|
3088
|
+
output.append("\nQuick Shortcuts:")
|
|
3021
3089
|
output.append("-" * 20)
|
|
3022
3090
|
shortcut_items = sorted(FRAMEWORK_SHORTCUTS.items())
|
|
3023
3091
|
for shorthand, framework_id in shortcut_items[:10]: # Show first 10
|
|
@@ -201,7 +201,7 @@ class ComplianceIntegration(ScannerIntegration, ABC):
|
|
|
201
201
|
self._load_existing_assessments()
|
|
202
202
|
|
|
203
203
|
self._cache_loaded = True
|
|
204
|
-
logger.info("
|
|
204
|
+
logger.info("Loaded existing records cache to prevent duplicates:")
|
|
205
205
|
logger.info(f" - Assets: {len(self._existing_assets_cache)}")
|
|
206
206
|
logger.info(f" - Issues: {len(self._existing_issues_cache)}")
|
|
207
207
|
logger.info(f" - Assessments: {len(self._existing_assessments_cache)}")
|
|
@@ -253,7 +253,7 @@ class ComplianceIntegration(ScannerIntegration, ABC):
|
|
|
253
253
|
parent_id=self.plan_id, parent_module=self.parent_module
|
|
254
254
|
)
|
|
255
255
|
all_issues.update(plan_issues)
|
|
256
|
-
logger.debug(f"
|
|
256
|
+
logger.debug(f"Found {len(plan_issues)} issues directly under plan {self.plan_id}")
|
|
257
257
|
|
|
258
258
|
# Method 2: Get issues associated with control implementations (matches scanner integration logic)
|
|
259
259
|
try:
|
|
@@ -274,11 +274,11 @@ class ComplianceIntegration(ScannerIntegration, ABC):
|
|
|
274
274
|
except Exception as e:
|
|
275
275
|
logger.debug(f"Could not load issue {issue_id}: {e}")
|
|
276
276
|
|
|
277
|
-
logger.debug(f"
|
|
277
|
+
logger.debug(f"Found {impl_issues_count} additional issues via control implementations")
|
|
278
278
|
except Exception as e:
|
|
279
279
|
logger.debug(f"Could not load issues by control implementation: {e}")
|
|
280
280
|
|
|
281
|
-
logger.debug(f"
|
|
281
|
+
logger.debug(f"Total unique issues found: {len(all_issues)} for plan {self.plan_id}")
|
|
282
282
|
|
|
283
283
|
wiz_issues = 0
|
|
284
284
|
for issue in all_issues:
|
|
@@ -287,11 +287,11 @@ class ComplianceIntegration(ScannerIntegration, ABC):
|
|
|
287
287
|
self._existing_issues_cache[issue.externalId] = issue
|
|
288
288
|
if "wiz-policy" in issue.externalId.lower():
|
|
289
289
|
wiz_issues += 1
|
|
290
|
-
logger.debug(f"
|
|
290
|
+
logger.debug(f"Cached Wiz issue: {issue.id} -> external_id: {issue.externalId}")
|
|
291
291
|
if hasattr(issue, "otherIdentifier") and issue.otherIdentifier:
|
|
292
292
|
self._existing_issues_cache[issue.otherIdentifier] = issue
|
|
293
293
|
|
|
294
|
-
logger.debug(f"
|
|
294
|
+
logger.debug(f"Cached {wiz_issues} Wiz policy issues out of {len(all_issues)} total issues")
|
|
295
295
|
|
|
296
296
|
except Exception as e:
|
|
297
297
|
logger.debug(f"Error loading existing issues: {e}")
|
|
@@ -1742,7 +1742,7 @@ class ScannerIntegration(ABC):
|
|
|
1742
1742
|
).create_or_update()
|
|
1743
1743
|
logger.debug("Added CWE property %s to issue %s", finding.plugin_id, issue.id)
|
|
1744
1744
|
|
|
1745
|
-
if ScannerVariables.useMilestones:
|
|
1745
|
+
if ScannerVariables.useMilestones and issue.id:
|
|
1746
1746
|
if (
|
|
1747
1747
|
existing_issue
|
|
1748
1748
|
and existing_issue.status == regscale_models.IssueStatus.Closed
|
|
@@ -1754,7 +1754,7 @@ class ScannerIntegration(ABC):
|
|
|
1754
1754
|
responsiblePersonId=self.assessor_id,
|
|
1755
1755
|
parentID=issue.id,
|
|
1756
1756
|
parentModule="issues",
|
|
1757
|
-
).
|
|
1757
|
+
).create()
|
|
1758
1758
|
logger.debug("Added milestone for issue %s from finding %s", issue.id, finding.external_id)
|
|
1759
1759
|
elif (
|
|
1760
1760
|
existing_issue
|
|
@@ -1767,7 +1767,7 @@ class ScannerIntegration(ABC):
|
|
|
1767
1767
|
responsiblePersonId=self.assessor_id,
|
|
1768
1768
|
parentID=issue.id,
|
|
1769
1769
|
parentModule="issues",
|
|
1770
|
-
).
|
|
1770
|
+
).create()
|
|
1771
1771
|
logger.debug("Added milestone for issue %s from finding %s", issue.id, finding.external_id)
|
|
1772
1772
|
elif not existing_issue:
|
|
1773
1773
|
regscale_models.Milestone(
|
|
@@ -1776,7 +1776,7 @@ class ScannerIntegration(ABC):
|
|
|
1776
1776
|
responsiblePersonId=self.assessor_id,
|
|
1777
1777
|
parentID=issue.id,
|
|
1778
1778
|
parentModule="issues",
|
|
1779
|
-
).
|
|
1779
|
+
).create()
|
|
1780
1780
|
logger.debug("Created milestone for issue %s from finding %s", issue.id, finding.external_id)
|
|
1781
1781
|
else:
|
|
1782
1782
|
logger.debug("No milestone created for issue %s from finding %s", issue.id, finding.external_id)
|
|
@@ -2661,7 +2661,7 @@ class ScannerIntegration(ABC):
|
|
|
2661
2661
|
issue.dateLastUpdated = get_current_datetime()
|
|
2662
2662
|
issue.save()
|
|
2663
2663
|
|
|
2664
|
-
if ScannerVariables.useMilestones:
|
|
2664
|
+
if ScannerVariables.useMilestones and issue.id:
|
|
2665
2665
|
regscale_models.Milestone(
|
|
2666
2666
|
title=f"Issue closed from {self.title} scan",
|
|
2667
2667
|
milestoneDate=issue.dateCompleted,
|
|
@@ -2669,7 +2669,7 @@ class ScannerIntegration(ABC):
|
|
|
2669
2669
|
completed=True,
|
|
2670
2670
|
parentID=issue.id,
|
|
2671
2671
|
parentModule="issues",
|
|
2672
|
-
).
|
|
2672
|
+
).create()
|
|
2673
2673
|
logger.debug("Created milestone for issue %s from %s tool", issue.id, self.title)
|
|
2674
2674
|
|
|
2675
2675
|
with count_lock:
|
|
@@ -1,9 +1,55 @@
|
|
|
1
1
|
{
|
|
2
2
|
"title": "CISA Catalog of Known Exploited Vulnerabilities",
|
|
3
|
-
"catalogVersion": "2025.08.
|
|
4
|
-
"dateReleased": "2025-08-
|
|
5
|
-
"count":
|
|
3
|
+
"catalogVersion": "2025.08.25",
|
|
4
|
+
"dateReleased": "2025-08-25T17:04:19.9796Z",
|
|
5
|
+
"count": 1404,
|
|
6
6
|
"vulnerabilities": [
|
|
7
|
+
{
|
|
8
|
+
"cveID": "CVE-2025-48384",
|
|
9
|
+
"vendorProject": "Git",
|
|
10
|
+
"product": "Git",
|
|
11
|
+
"vulnerabilityName": "Git Link Following Vulnerability",
|
|
12
|
+
"dateAdded": "2025-08-25",
|
|
13
|
+
"shortDescription": "Git contains a link following vulnerability that stems from Git\u2019s inconsistent handling of carriage return characters in configuration files.",
|
|
14
|
+
"requiredAction": "Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.",
|
|
15
|
+
"dueDate": "2025-09-15",
|
|
16
|
+
"knownRansomwareCampaignUse": "Unknown",
|
|
17
|
+
"notes": "This vulnerability affects a common open-source component, third-party library, or a protocol used by different products. For more information, please see: https:\/\/github.com\/git\/git\/security\/advisories\/GHSA-vwqx-4fm8-6qc9 ; https:\/\/access.redhat.com\/errata\/RHSA-2025:13933 ; https:\/\/alas.aws.amazon.com\/AL2\/ALAS2-2025-2941.html ; https:\/\/linux.oracle.com\/errata\/ELSA-2025-11534.html ; https:\/\/msrc.microsoft.com\/update-guide\/vulnerability\/CVE-2025-48384 ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2025-48384",
|
|
18
|
+
"cwes": [
|
|
19
|
+
"CWE-59",
|
|
20
|
+
"CWE-436"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"cveID": "CVE-2024-8068",
|
|
25
|
+
"vendorProject": "Citrix",
|
|
26
|
+
"product": "Session Recording",
|
|
27
|
+
"vulnerabilityName": "Citrix Session Recording Improper Privilege Management Vulnerability",
|
|
28
|
+
"dateAdded": "2025-08-25",
|
|
29
|
+
"shortDescription": "Citrix Session Recording contains an improper privilege management vulnerability that could allow for privilege escalation to NetworkService Account access. An attacker must be an authenticated user in the same Windows Active Directory domain as the session recording server domain.",
|
|
30
|
+
"requiredAction": "Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.",
|
|
31
|
+
"dueDate": "2025-09-15",
|
|
32
|
+
"knownRansomwareCampaignUse": "Unknown",
|
|
33
|
+
"notes": "https:\/\/support.citrix.com\/external\/article\/691941\/citrix-session-recording-security-bullet.html ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2024-8068",
|
|
34
|
+
"cwes": [
|
|
35
|
+
"CWE-269"
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"cveID": "CVE-2024-8069",
|
|
40
|
+
"vendorProject": "Citrix",
|
|
41
|
+
"product": "Session Recording",
|
|
42
|
+
"vulnerabilityName": "Citrix Session Recording Deserialization of Untrusted Data Vulnerability",
|
|
43
|
+
"dateAdded": "2025-08-25",
|
|
44
|
+
"shortDescription": "Citrix Session Recording contains a deserialization of untrusted data vulnerability that allows limited remote code execution with privilege of a NetworkService Account access. Attacker must be an authenticated user on the same intranet as the session recording server.",
|
|
45
|
+
"requiredAction": "Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.",
|
|
46
|
+
"dueDate": "2025-09-15",
|
|
47
|
+
"knownRansomwareCampaignUse": "Unknown",
|
|
48
|
+
"notes": "https:\/\/support.citrix.com\/external\/article\/691941\/citrix-session-recording-security-bullet.html ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2024-8069",
|
|
49
|
+
"cwes": [
|
|
50
|
+
"CWE-502"
|
|
51
|
+
]
|
|
52
|
+
},
|
|
7
53
|
{
|
|
8
54
|
"cveID": "CVE-2025-43300",
|
|
9
55
|
"vendorProject": "Apple",
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
"""Class for milestone model in RegScale platform"""
|
|
4
4
|
|
|
5
5
|
from typing import Optional
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
from pydantic import Field, field_validator, model_validator
|
|
7
8
|
|
|
8
9
|
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
9
10
|
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
@@ -14,27 +15,44 @@ class Milestone(RegScaleModel):
|
|
|
14
15
|
|
|
15
16
|
_module_slug = "milestones"
|
|
16
17
|
_module_string = "milestones"
|
|
18
|
+
_unique_fields = ["title", "parentModule"]
|
|
17
19
|
|
|
18
20
|
title: str
|
|
19
21
|
id: int = 0
|
|
20
22
|
isPublic: Optional[bool] = True
|
|
21
23
|
milestoneDate: Optional[str] = Field(default_factory=get_current_datetime)
|
|
22
24
|
responsiblePersonId: Optional[str] = None
|
|
23
|
-
predecessorStepId: Optional[int] =
|
|
25
|
+
predecessorStepId: Optional[int] = None
|
|
24
26
|
completed: Optional[bool] = False
|
|
25
|
-
dateCompleted: Optional[str] =
|
|
27
|
+
dateCompleted: Optional[str] = None
|
|
26
28
|
notes: Optional[str] = ""
|
|
27
29
|
parentID: Optional[int] = None
|
|
28
30
|
parentModule: str = ""
|
|
29
31
|
|
|
30
|
-
@
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
@field_validator("milestoneDate")
|
|
33
|
+
@classmethod
|
|
34
|
+
def validate_milestone_date(cls, v: Optional[str]) -> str:
|
|
35
|
+
"""Ensure milestoneDate is never empty."""
|
|
36
|
+
if not v or v == "":
|
|
37
|
+
return get_current_datetime()
|
|
38
|
+
return v
|
|
39
|
+
|
|
40
|
+
@field_validator("dateCompleted")
|
|
41
|
+
@classmethod
|
|
42
|
+
def set_date_completed(cls, v: Optional[str], info) -> Optional[str]:
|
|
43
|
+
"""Set dateCompleted based on completed field."""
|
|
44
|
+
completed = info.data.get("completed", False)
|
|
45
|
+
if completed and (v is None or v == ""):
|
|
46
|
+
return get_current_datetime()
|
|
47
|
+
if not completed:
|
|
48
|
+
return None
|
|
49
|
+
return v
|
|
50
|
+
|
|
51
|
+
@model_validator(mode="after")
|
|
52
|
+
def validate_completion(self):
|
|
53
|
+
"""Ensure dateCompleted is set when completed is True."""
|
|
54
|
+
if self.completed and (self.dateCompleted is None or self.dateCompleted == ""):
|
|
55
|
+
self.dateCompleted = get_current_datetime()
|
|
56
|
+
elif not self.completed:
|
|
57
|
+
self.dateCompleted = None
|
|
58
|
+
return self
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
regscale/__init__.py,sha256=ZygAIkX6Nbjag1czWdQa-yP-GM1mBE_9ss21Xh__JFc,34
|
|
2
|
-
regscale/_version.py,sha256=
|
|
2
|
+
regscale/_version.py,sha256=c23bJjOSOin3Rj2jQMCSQSWCsJkFOj3c3AkLRqbD5mc,1198
|
|
3
3
|
regscale/regscale.py,sha256=xcxnTwEwWgfO3Fnp0LVo32SZCJzAswq3WDZgm21nHnI,30914
|
|
4
4
|
regscale/airflow/__init__.py,sha256=yMwN0Bz4JbM0nl5qY_hPegxo_O2ilhTOL9PY5Njhn-s,270
|
|
5
5
|
regscale/airflow/click_dags.py,sha256=H3SUR5jkvInNMv1gu-VG-Ja_H-kH145CpQYNalWNAbE,4520
|
|
@@ -36,7 +36,7 @@ regscale/core/lazy_group.py,sha256=S2-nA5tzm47A929NOTqGkzrzKuZQDlq2OAPbNnG1W1Q,2
|
|
|
36
36
|
regscale/core/login.py,sha256=-8vy1HVAtv1iARnZh6uzYtwmx8VFYPwLYR0QAf1ttCk,2714
|
|
37
37
|
regscale/core/app/__init__.py,sha256=nGcCN1vWBAnZzoccIlt0jwWQdegCOrBWOB7LPhQkQSs,96
|
|
38
38
|
regscale/core/app/api.py,sha256=CSyUCV6haBAQ9IyE1FViJcAfTcoS5GJRaULwnRoAV9U,23499
|
|
39
|
-
regscale/core/app/application.py,sha256=
|
|
39
|
+
regscale/core/app/application.py,sha256=O-Z0EVQuGIWAeUSjz2IK1LnUP5zF1YNOb4gxZ79B1LI,31903
|
|
40
40
|
regscale/core/app/logz.py,sha256=8AdBKmquv45JGi5fCMc38JqQg6-FpUONGmqfd5EGwrI,2583
|
|
41
41
|
regscale/core/app/internal/__init__.py,sha256=rod4nmE7rrYDdbuYF4mCWz49TK_2r-v4tWy1UHW63r0,4808
|
|
42
42
|
regscale/core/app/internal/admin_actions.py,sha256=hOdma7QGwFblmxEj9UTjiWWmZGUS5_ZFtxL2qZdhf-Q,7443
|
|
@@ -111,10 +111,10 @@ regscale/exceptions/validation_exception.py,sha256=_DW_GARtPr_Dyy8tolnvC_AYsHRsU
|
|
|
111
111
|
regscale/integrations/__init__.py,sha256=Sqthp3Jggo7co_go380cLn3OAb0cHwqL609_4QJSFBY,58
|
|
112
112
|
regscale/integrations/api_paginator.py,sha256=73rjaNM9mGv8evHAeoObXEjZPg-bJuGPo60ewCLEil8,33192
|
|
113
113
|
regscale/integrations/api_paginator_example.py,sha256=lEuYI-xEGcjnXuIzbCobCP0YRuukLF0s8S3d382SAH4,12119
|
|
114
|
-
regscale/integrations/compliance_integration.py,sha256=
|
|
114
|
+
regscale/integrations/compliance_integration.py,sha256=aR13rcMh-BTpr_ibENPQZ1z5rlhtuqpPGRI9YfbqJjw,68394
|
|
115
115
|
regscale/integrations/integration_override.py,sha256=HjYBCuvNpU3t3FptaqYAkdexLFOZBAFrFE9xU0RD1Nc,5867
|
|
116
116
|
regscale/integrations/jsonl_scanner_integration.py,sha256=l8nq_T3rE1XX-6HxrNHm3xzxCNWbIjxQvGMdtZWs7KQ,57003
|
|
117
|
-
regscale/integrations/scanner_integration.py,sha256=
|
|
117
|
+
regscale/integrations/scanner_integration.py,sha256=o7RdZ7Z0x0Ldhh5JrjUx1qFGKiJLw_y-6mFyhyA2P1k,145526
|
|
118
118
|
regscale/integrations/variables.py,sha256=MfQ34WuYVN5437A9sZ2ssHRkA3gFhMHfk1DVasceGmY,2336
|
|
119
119
|
regscale/integrations/commercial/__init__.py,sha256=LZj1qV5f7RdHIOfedDVELV62ADe5gyNccWayHMF1aVc,14026
|
|
120
120
|
regscale/integrations/commercial/ad.py,sha256=YXSmK8vRf6yi2GnREGa5GrE6GelhFrLj44SY8AO1pK0,15509
|
|
@@ -240,7 +240,7 @@ regscale/integrations/commercial/wizv2/data_fetcher.py,sha256=tMdwWfaQCqLpZg9tGE
|
|
|
240
240
|
regscale/integrations/commercial/wizv2/finding_processor.py,sha256=Rn2dYob4cz24_Ks-UTwNQe-KQ6hmFWS6GB8PQXV0ZPE,11361
|
|
241
241
|
regscale/integrations/commercial/wizv2/issue.py,sha256=PA_7BNpCnHGoAc1caU6COGHaIIvCBvIt6DLn3L7Bilo,13451
|
|
242
242
|
regscale/integrations/commercial/wizv2/parsers.py,sha256=dsSMiZaUrBXbuW7U-I5nLoF-TQlpvXys83sTSqT4Yks,11819
|
|
243
|
-
regscale/integrations/commercial/wizv2/policy_compliance.py,sha256=
|
|
243
|
+
regscale/integrations/commercial/wizv2/policy_compliance.py,sha256=a2VzMxwGiGeIcU8FnyCH6I0z0wdyXeVQPFM7hV9Td-k,133181
|
|
244
244
|
regscale/integrations/commercial/wizv2/policy_compliance_helpers.py,sha256=-KAlDxMiojyUX2DtUi3uVbpmFhDLtGs7wj11MPBCaRE,22174
|
|
245
245
|
regscale/integrations/commercial/wizv2/sbom.py,sha256=QcGaYiBGtZ3mBcbo-KGl-I2u6QHKAIinTk26LPy0Kng,4466
|
|
246
246
|
regscale/integrations/commercial/wizv2/scanner.py,sha256=weSjSBFvvgHmMJp4lpjgomgvBIJ7rjpg_7W7JW-ds-A,74566
|
|
@@ -320,7 +320,7 @@ regscale/models/integration_models/azure_alerts.py,sha256=2etrpvcxa7jVQrc98bJlVG
|
|
|
320
320
|
regscale/models/integration_models/base64.py,sha256=sxV6O5qY1_TstJENX5jBPsSdQwmA83-NNhgJFunXiZE,570
|
|
321
321
|
regscale/models/integration_models/burp.py,sha256=FBEBkH3U0Q8vq71FFoWnvgLRF5Hkr9GYmQFmNNHFrVk,16932
|
|
322
322
|
regscale/models/integration_models/burp_models.py,sha256=UytDTAcCaxyu-knFkm_mEUH6UmWK3OTXKSC9Sc6OjVs,3669
|
|
323
|
-
regscale/models/integration_models/cisa_kev_data.json,sha256=
|
|
323
|
+
regscale/models/integration_models/cisa_kev_data.json,sha256=kBsfInlBo4eaPjn8uFe7b3JSv51xtj7wjVCoNtWrG9I,1257565
|
|
324
324
|
regscale/models/integration_models/defender_data.py,sha256=jsAcjKxiGmumGerj7xSWkFd6r__YpuKDnYX5o7xHDiE,2844
|
|
325
325
|
regscale/models/integration_models/defenderimport.py,sha256=Ze4kgwns-IYPyO7sBjEzW8PXWlxwU-DAo2fIyRcTC3k,6242
|
|
326
326
|
regscale/models/integration_models/drf.py,sha256=Aq7AdLa_CH97NrnR-CxaFI22JjVN9uCxVN7Z-BBUaNU,18896
|
|
@@ -415,7 +415,7 @@ regscale/models/regscale_models/line_of_inquiry.py,sha256=Uu0lQEhif0W6yTSkJo27Gy
|
|
|
415
415
|
regscale/models/regscale_models/link.py,sha256=lAY4Ig3Menm1EqfcAbVJ7jsCsRO5tWtJIf-9-G9FXT8,6593
|
|
416
416
|
regscale/models/regscale_models/master_assessment.py,sha256=t03-8vQJ7hnPNgEU0GSC1XGKOgAqHKuIupbt5IjJvtI,7322
|
|
417
417
|
regscale/models/regscale_models/meta_data.py,sha256=Fg8rrWSTx3K00QkF4glH9UdY9OFWJ4_UqxleLSSbx8I,2482
|
|
418
|
-
regscale/models/regscale_models/milestone.py,sha256=
|
|
418
|
+
regscale/models/regscale_models/milestone.py,sha256=HiBdx1uzasl3Crb03j9qdowCHUy93nTOuklLs_V2SSM,1943
|
|
419
419
|
regscale/models/regscale_models/module.py,sha256=a7lalHmVTQ04ZILnJxuFWdHYDtyusBMTtonD4ICL-Wc,7272
|
|
420
420
|
regscale/models/regscale_models/modules.py,sha256=yeva_tct88o2NFt93_zmqUcXZ3LucVbAv5FvQPru3cQ,8551
|
|
421
421
|
regscale/models/regscale_models/objective.py,sha256=aJIpmkZ-NscqV2y8SGB4HYzm615b6mklyHnW9bL2ljk,249
|
|
@@ -533,9 +533,9 @@ tests/regscale/models/test_regscale_model.py,sha256=ZsrEZkC4EtdIsoQuayn1xv2gEGcV
|
|
|
533
533
|
tests/regscale/models/test_report.py,sha256=IqUq7C__a1_q_mLaz0PE9Lq6fHggBsB14-AzEYNBxLw,4666
|
|
534
534
|
tests/regscale/models/test_tenable_integrations.py,sha256=PNJC2Zu6lv1xj7y6e1yOsz5FktSU3PRKb5x3n5YG3w0,4072
|
|
535
535
|
tests/regscale/models/test_user_model.py,sha256=e9olv28qBApgnvK6hFHOgXjUC-pkaV8aGDirEIWASL4,4427
|
|
536
|
-
regscale_cli-6.21.2.
|
|
537
|
-
regscale_cli-6.21.2.
|
|
538
|
-
regscale_cli-6.21.2.
|
|
539
|
-
regscale_cli-6.21.2.
|
|
540
|
-
regscale_cli-6.21.2.
|
|
541
|
-
regscale_cli-6.21.2.
|
|
536
|
+
regscale_cli-6.21.2.2.dist-info/LICENSE,sha256=ytNhYQ9Rmhj_m-EX2pPq9Ld6tH5wrqqDYg-fCf46WDU,1076
|
|
537
|
+
regscale_cli-6.21.2.2.dist-info/METADATA,sha256=7yq5fry5SL1DvzcbSeD18IguQQoEOpA6s7lHM2nR2zA,34955
|
|
538
|
+
regscale_cli-6.21.2.2.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
539
|
+
regscale_cli-6.21.2.2.dist-info/entry_points.txt,sha256=cLOaIP1eRv1yZ2u7BvpE3aB4x3kDrDwkpeisKOu33z8,269
|
|
540
|
+
regscale_cli-6.21.2.2.dist-info/top_level.txt,sha256=Uv8VUCAdxRm70bgrD4YNEJUmDhBThad_1aaEFGwRByc,15
|
|
541
|
+
regscale_cli-6.21.2.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|