Add Server Buddy desktop app with local Linux assessment and reporting

This commit is contained in:
2026-10-30 09:46:01 -07:00
commit 365f97942a
29 changed files with 1789 additions and 0 deletions

89
tests/test_linux.py Normal file
View File

@@ -0,0 +1,89 @@
import json
from pathlib import Path
import tempfile
import unittest
from unittest.mock import patch
from server_buddy.collectors.linux import (collect_local_linux, parse_connections,
parse_units, run_command, CollectionCancelled)
from server_buddy.collectors.demo import collect_demo, LINUX_DEMO_HOST
from server_buddy.analyzers.assessment import assess
from server_buddy.reporting.export import export_html
class LinuxTests(unittest.TestCase):
def test_service_states_and_startup(self):
rows = parse_units('nginx.service loaded active running Web server\nexample.service loaded inactive dead Example\n',
'nginx.service enabled enabled\nexample.service disabled disabled\n')
self.assertEqual(rows[0]['state'], 'Running')
self.assertEqual(rows[0]['startup'], 'enabled')
self.assertEqual(rows[1]['state'], 'inactive/dead')
def test_ipv4_ipv6_and_unprivileged_connections(self):
rows = parse_connections('LISTEN 0 128 0.0.0.0:22 0.0.0.0:*\nESTAB 0 0 [::1]:443 [::1]:51234 users:(("nginx",pid=123,fd=7))\n')
self.assertEqual(rows[0]['remote_port'], 0)
self.assertIsNone(rows[0]['pid'])
self.assertEqual(rows[1]['local_address'], '::1')
self.assertEqual(rows[1]['state'], 'Established')
self.assertEqual(rows[1]['process'], 'nginx')
self.assertEqual(rows[1]['direction'], 'Unknown')
@patch('server_buddy.collectors.linux.platform.system', return_value='Windows')
def test_wrong_execution_platform(self, system):
with self.assertRaises(ValueError):
collect_local_linux()
@patch('server_buddy.collectors.linux.platform.system', return_value='Linux')
def test_partial_failures_never_use_demo(self, system):
def unavailable(args, **kwargs):
raise RuntimeError('SECRET diagnostics must not be reported')
data = collect_local_linux(runner=unavailable)
self.assertFalse(data['synthetic'])
self.assertEqual(data['checks']['services']['status'], 'failed')
self.assertEqual(data['checks']['network']['status'], 'failed')
self.assertEqual(data['checks']['software']['status'], 'failed')
self.assertEqual(data['inventory']['services'], [])
self.assertNotIn('SECRET', json.dumps(data))
self.assertEqual(data['checks']['certificates']['status'], 'not_collected')
@patch('server_buddy.collectors.linux.platform.system', return_value='Linux')
def test_cancel(self, system):
with self.assertRaises(CollectionCancelled):
collect_local_linux(cancelled=lambda: True)
def test_mint_and_rhel_package_parsing(self):
for rpm in [False, True]:
def command(args, **kwargs):
if args[0] == 'ip':
return '[]'
if args[0] == 'rpm':
return 'nginx\t1.2-1\tExample vendor\n'
if args[0] == 'dpkg-query':
return 'installed\tnginx:amd64\t1.2\nconfig-files\tremoved\t1.0\n'
return ''
with self.subTest(rpm=rpm), patch('server_buddy.collectors.linux.platform.system', return_value='Linux'), patch('server_buddy.collectors.linux.Path.is_file', return_value=rpm):
data = collect_local_linux(runner=command)
self.assertEqual(len(data['inventory']['software']), 1)
self.assertIn('nginx', data['inventory']['software'][0]['name'])
self.assertEqual(data['checks']['software']['status'], 'partial')
def test_local_report_source_and_unclassified_services(self):
data = collect_demo(LINUX_DEMO_HOST)
data['synthetic'] = False
data['server']['collection_source'] = 'Local Linux read-only collection'
data['inventory']['services'] = [{'name': 'desktop-example.service', 'state': 'Running'}]
result = assess(data)
self.assertFalse(any(f['category'] == 'Active service' for f in result['findings']))
self.assertTrue(any(f['category'] == 'Unclassified services' for f in result['findings']))
with tempfile.TemporaryDirectory() as folder:
path = Path(folder) / 'report.html'
export_html(path, data, result)
self.assertIn('LOCAL LINUX INVENTORY', path.read_text())
self.assertNotIn('IMPORTED INVENTORY', path.read_text())
@unittest.skipUnless(__import__('sys').platform.startswith('linux'), 'Linux command test')
def test_command_timeout_and_cancellation(self):
with self.assertRaisesRegex(RuntimeError, 'timed out'):
run_command(['sleep', '1'], timeout=.05)
with self.assertRaises(CollectionCancelled):
run_command(['sleep', '1'], cancelled=lambda: True)