1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
# SPDX-License-Identifier: GPL-3.0-or-later
"""Post-install checks: services, timers, and their functional health.
Parity port of validate_firewall, validate_dns_config, validate_avahi,
validate_fail2ban, validate_networkmanager, and validate_all_services /
validate_service_functions.
Mapping of the shell sweep's three outcomes:
- validation_fail (hard) -> assert
- validation_warn (soft) -> pytest.skip with the reason (visible, never red)
- validation_skip (precond)-> pytest.skip gated on a fixture
"""
import pytest
# Required services: (name, must_be_active). ufw can't activate in the VM (no
# iptables kernel modules), so it's enabled-only; cronie/atd are enabled-only too.
REQUIRED_ENABLED_ACTIVE = ["sshd", "systemd-resolved", "fail2ban", "NetworkManager", "rngd"]
REQUIRED_ENABLED_ONLY = ["ufw", "cronie", "atd"]
REQUIRED_TIMERS = ["reflector.timer", "paccache.timer"]
OPTIONAL_SERVICES = ["avahi-daemon", "bluetooth", "cups", "docker", "tailscaled"]
@pytest.mark.attribution("archsetup")
@pytest.mark.parametrize("svc", REQUIRED_ENABLED_ACTIVE)
def test_required_service_enabled_and_active(host, svc):
s = host.service(svc)
assert s.is_enabled, "%s should be enabled" % svc
assert s.is_running, "%s should be active" % svc
@pytest.mark.smoke
@pytest.mark.attribution("archsetup")
@pytest.mark.parametrize("svc", REQUIRED_ENABLED_ONLY)
def test_required_service_enabled(host, svc):
assert host.service(svc).is_enabled, "%s should be enabled" % svc
@pytest.mark.attribution("archsetup")
@pytest.mark.parametrize("timer", REQUIRED_TIMERS)
def test_required_timer_enabled(host, timer):
assert host.service(timer).is_enabled, "%s should be enabled" % timer
@pytest.mark.parametrize("svc", OPTIONAL_SERVICES)
def test_optional_service(host, svc):
# Optional: warn-if-missing in the shell sweep -> skip here so it never reds.
if not host.service(svc).is_enabled:
pytest.skip("%s not enabled (optional)" % svc)
@pytest.mark.attribution("archsetup")
def test_dns_over_tls_dropin_present(host):
# archsetup ships /etc/systemd/resolved.conf.d/dns-over-tls.conf.
assert host.file("/etc/systemd/resolved.conf.d/dns-over-tls.conf").exists
@pytest.mark.attribution("archsetup")
def test_fail2ban_responds(host):
assert host.run("fail2ban-client status").rc == 0
@pytest.mark.attribution("archsetup")
def test_networkmanager_responds(host):
assert host.run("nmcli general status").rc == 0
@pytest.mark.attribution("archsetup")
def test_log_cleanup_cron_installed(host, target_user):
out = host.run("sudo -u %s crontab -l" % target_user).stdout
assert "log-cleanup" in out, "log-cleanup entry missing from user crontab"
@pytest.mark.attribution("archsetup")
def test_syncthing_user_lingering_enabled(host, target_user):
# syncthing runs as a user service; lingering must be on for autostart.
assert host.file("/var/lib/systemd/linger/%s" % target_user).exists
def test_dns_resolution(host):
# Network-dependent; advisory in the shell sweep. Skip on failure.
if host.run("resolvectl query archlinux.org").rc != 0:
pytest.skip("DNS resolution query failed (network-dependent)")
def test_mdns_resolves(host, on_slirp):
# mDNS needs multicast, which QEMU slirp doesn't pass.
if on_slirp:
pytest.skip("mDNS not possible on slirp networking (no multicast)")
if not host.service("avahi-daemon").is_enabled:
pytest.skip("avahi-daemon not enabled")
hostname = host.run("hostname").stdout.strip()
assert host.run("ping -c 1 -W 2 %s.local" % hostname).rc == 0
def test_docker_functional(host):
if not host.service("docker").is_enabled:
pytest.skip("docker not enabled")
if not host.service("docker").is_running:
# archsetup enables docker for next boot, not --now; pre-reboot this is correct.
pytest.skip("docker enabled but not started (starts on boot by design)")
assert host.run("docker info").rc == 0
|