Files
Samsara/tests/test_ui.py
oceans2alaska 610a3bb447 Privacy hardening, remote-peer IP masking and review fixes
- Add privacy projection (core/privacy.py), private report storage, bounded
  process capture; omit identities, free text and unapproved paths
- Mask remote peer IPs: only loopback/host/wildcard stay numeric, others are
  reduced to remote_scope private/public (schema + scoring updated)
- Map ss TCP states to canonical names; ASCII-only numeric fields; fix
  "Microsoft Visual C++" product matching (Python and PowerShell)
- Merge 7fed3b9: -Diagnostic switch, serialization exit code 3, PS7 module
  path, UI error detail; keep hardened task/certificate collectors
- Add audit docs, privacy docs and regression tests

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-04 18:50:24 -08:00

191 lines
10 KiB
Python

import os
os.environ.setdefault('QT_QPA_PLATFORM', 'offscreen')
import time
import tempfile
from pathlib import Path
import unittest
from unittest.mock import patch
try:
from PySide6.QtWidgets import QApplication
from samsara.ui.window import MainWindow
except ImportError:
QApplication = None
from samsara.collectors.demo import collect_demo, LINUX_DEMO_HOST
@unittest.skipIf(QApplication is None, 'PySide6 not installed')
class UITests(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.app = QApplication.instance() or QApplication([])
def finish(self, window):
deadline = time.monotonic() + 5
while window.job is not None and time.monotonic() < deadline:
self.app.processEvents()
time.sleep(.01)
self.assertIsNone(window.job)
def test_default_workflow_navigation_and_no_fabricated_history(self):
window = MainWindow()
self.assertEqual(window.windowTitle(), 'Samsara')
self.assertEqual(window.source.currentData(), 'local')
self.assertEqual(window.target.currentData(), 'auto')
self.assertIsNone(window.data)
self.assertEqual(window.history, [])
self.assertFalse(window.report_buttons[0].isEnabled())
self.assertEqual(window.nav.item(0).text(), 'Summary')
for index in range(5):
window.nav.setCurrentRow(index)
self.assertEqual(window.pages.currentIndex(), {0: 1, 1: 0, 2: 2, 3: 3, 4: 4}[index])
window.close()
def test_samples_details_and_history(self):
window = MainWindow()
for source, expected in [('linux_demo', 'linux'), ('windows_demo', 'windows')]:
window.source.setCurrentIndex(window.source.findData(source))
self.assertFalse(window.target.isEnabled())
window.start_collection()
self.finish(window)
self.assertEqual(window.data['server']['platform'], expected)
self.assertIn('Synthetic', window.banner.text())
self.assertEqual(window.nav.currentRow(), 0)
self.assertEqual(window.result_tabs.tabText(0), 'Summary')
self.assertIn('/100', window.retirement_score.text())
self.assertIn('Version:', window.os_version.text())
for index in range(1, window.result_tabs.count()):
window.result_tabs.setCurrentIndex(index)
self.assertGreaterEqual(list(window.detail_areas.values())[index - 1].count(), 1)
window.open_history(window.history_list.item(0))
self.assertEqual(window.data['server']['platform'], 'linux')
self.assertEqual(len(window.records), 2)
window.close()
def test_auto_detect_runs_local_collector_and_saves_report(self):
data = collect_demo(LINUX_DEMO_HOST)
data['synthetic'] = False
data['server']['collection_source'] = 'Local Linux read-only collection'
detected = {'platform': 'linux', 'family': 'linux', 'version': '22', 'name': 'Local Linux'}
with patch('samsara.ui.window.detect_local_os', return_value=detected) as detection, patch('samsara.ui.window.collect_local_linux', return_value=data) as collector:
window = MainWindow()
window.analyze_button.click()
self.assertFalse(window.analyze_button.isEnabled())
self.finish(window)
detection.assert_called_once()
collector.assert_called_once()
self.assertIn('Local Linux', window.banner.text())
self.assertTrue(window.analyze_button.isEnabled())
self.assertTrue(window.report_buttons[0].isEnabled())
with tempfile.TemporaryDirectory() as folder:
report = Path(folder) / 'local.html'
with patch('samsara.core.storage._verify_windows_acl'), patch('samsara.core.storage.report_directory',return_value=Path(folder)), patch('samsara.ui.window.report_directory',return_value=Path(folder)), patch('samsara.ui.window.QFileDialog.getSaveFileName', return_value=(str(report), '')), patch('samsara.ui.window.QMessageBox.information'):
window.quick_save.click()
self.assertIn('LOCAL LINUX INVENTORY', report.read_text())
window.close()
def test_mismatched_profile_and_windows_failure_keep_prior_results(self):
window = MainWindow()
window.collection_done(collect_demo(LINUX_DEMO_HOST))
previous = window.data
detected = {'platform': 'linux', 'family': 'linux', 'version': '22', 'name': 'Local Linux'}
with patch('samsara.ui.window.detect_local_os', return_value=detected), patch('samsara.ui.window.collect_local_linux') as collector:
window.target.setCurrentIndex(window.target.findData('rhel:9'))
window.start_collection()
self.finish(window)
collector.assert_not_called()
self.assertIn('does not match', window.status.text())
self.assertIs(window.data, previous)
with patch('samsara.ui.window.detect_local_os', return_value={'platform': 'windows', 'family': 'windows', 'version': '', 'name': 'Windows'}), patch('samsara.ui.window.collect_local_windows', side_effect=ValueError('Windows identity collection failed.')):
window.start_collection()
self.finish(window)
self.assertIn('identity collection failed', window.status.text())
self.assertIs(window.data, previous)
window.close()
def test_import_requires_file_and_reads_recorded_os(self):
window = MainWindow()
window.source.setCurrentIndex(window.source.findData('file'))
self.assertFalse(window.target.isEnabled())
window.start_collection()
self.assertIn('Choose an inventory', window.status.text())
with patch('samsara.ui.window.load_inventory', return_value=collect_demo(LINUX_DEMO_HOST)) as loader, patch('samsara.ui.window.detect_local_os') as detect:
window.inventory_path.setText('/tmp/saved-inventory.json')
window.start_collection()
self.finish(window)
loader.assert_called_once_with('/tmp/saved-inventory.json')
detect.assert_not_called()
window.close()
def test_windows_local_route_preserves_summary_history_and_export(self):
import json
data = json.loads(Path('tests/fixtures/windows/server-2025.json').read_text())
data['synthetic'] = False
data['server']['collection_source'] = 'Local Windows read-only collection'
with patch('samsara.ui.window.detect_local_os', return_value={'platform': 'windows', 'family': 'windows', 'version': '', 'name': 'Windows'}), patch('samsara.ui.window.collect_local_windows', return_value=data) as collector, patch('samsara.ui.window.collect_local_linux') as linux:
window = MainWindow()
window.target.setCurrentIndex(window.target.findData('windows:2025'))
window.start_collection()
self.assertFalse(window.analyze_button.isEnabled())
self.finish(window)
collector.assert_called_once()
self.assertEqual(collector.call_args.kwargs['profile'], 'windows:2025')
linux.assert_not_called()
self.assertIn('Local Windows', window.banner.text())
self.assertIn('2025', window.os_version.text())
self.assertEqual(len(window.records), 1)
self.assertEqual(window.nav.currentRow(), 0)
self.assertTrue(window.report_buttons[0].isEnabled())
with tempfile.TemporaryDirectory() as folder:
report = Path(folder)/'windows.html'
with patch('samsara.core.storage._verify_windows_acl'), patch('samsara.core.storage.report_directory',return_value=Path(folder)), patch('samsara.ui.window.report_directory',return_value=Path(folder)), patch('samsara.ui.window.QFileDialog.getSaveFileName', return_value=(str(report), '')), patch('samsara.ui.window.QMessageBox.information'):
window.quick_save.click()
self.assertIn('LOCAL WINDOWS INVENTORY', report.read_text())
window.close()
def test_policy_changes_preserve_history_and_confidence_is_visible(self):
import json
from samsara.analyzers.policy import load_policy
window=MainWindow()
fixture=Path('tests/fixtures/scoring/active_sql_server.json')
window.collection_done(json.loads(fixture.read_text()))
self.assertEqual(window.assessment['score'],70)
original_policy=window.assessment['scoring']['policy_id']
self.assertIn('Confidence:',window.coverage_note.text())
self.assertIn('Coverage gaps do not add risk points',window.coverage_note.text())
with tempfile.TemporaryDirectory() as folder:
policy=load_policy()
policy['scores']['observed_application_clients']=55
path=Path(folder)/'policy.json'
path.write_text(json.dumps(policy))
with patch('samsara.ui.window.QFileDialog.getOpenFileName',return_value=(str(path),'')):
window.choose_policy()
window.source.setCurrentIndex(window.source.findData('file'))
window.inventory_path.setText(str(fixture.resolve()))
window.start_collection()
self.assertFalse(window.policy_button.isEnabled())
self.finish(window)
self.assertEqual(window.assessment['score'],55)
self.assertNotEqual(window.assessment['scoring']['policy_id'],original_policy)
window.open_history(window.history_list.item(0))
self.assertEqual(window.assessment['score'],70)
self.assertEqual(window.assessment['scoring']['policy_id'],original_policy)
window.reset_policy()
window.close()
def test_privacy_and_bounded_history_clear(self):
import json
window=MainWindow()
raw=collect_demo(LINUX_DEMO_HOST)
raw['server']['hostname']='SYNTHETIC_PERSON_UI_CANARY'
for _ in range(12): window.collection_done(raw)
self.assertEqual(len(window.records),10)
self.assertEqual(window.history_list.count(),10)
self.assertNotIn('SYNTHETIC_PERSON_UI_CANARY',json.dumps(window.records))
window.clear_history_button.click()
self.assertEqual(window.records,[])
self.assertEqual(window.history,[])
self.assertIsNone(window.data)
self.assertFalse(window.quick_save.isEnabled())
self.assertEqual(window.scheduled_jobs.text(),'')
window.close()