90 lines
4.6 KiB
Python
90 lines
4.6 KiB
Python
import json
|
|
from pathlib import Path
|
|
import tempfile
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
from samsara.collectors.linux import (collect_local_linux, parse_connections,
|
|
parse_units, run_command, CollectionCancelled)
|
|
from samsara.collectors.demo import collect_demo, LINUX_DEMO_HOST
|
|
from samsara.analyzers.assessment import assess
|
|
from samsara.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('samsara.collectors.linux.platform.system', return_value='Windows')
|
|
def test_wrong_execution_platform(self, system):
|
|
with self.assertRaises(ValueError):
|
|
collect_local_linux()
|
|
|
|
@patch('samsara.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('samsara.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('samsara.collectors.linux.platform.system', return_value='Linux'), patch('samsara.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)
|