The cis490-orchestrator unit only loaded lab-host.env, which has no MSFRPC_PASSWORD. run_tier3_demo.py exits rc=2 immediately if the var is unset. All tier3 slots were failing in ~240ms. Add EnvironmentFile=-/etc/cis490/msfrpc.env (the '-' prefix silences the error on Tier-2-only hosts where the file doesn't exist yet). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
49 lines
2 KiB
Desktop File
49 lines
2 KiB
Desktop File
[Unit]
|
|
Description=CIS490 lab-host episode orchestrator (fleet mode)
|
|
Documentation=https://maxgit.wg/spectral/CIS490
|
|
# Episodes need KVM. msfrpcd (for Tier 3+) is brought up out-of-band
|
|
# by cis490-msfrpcd.service when installed.
|
|
After=network-online.target wg-quick@wg0.service
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=cis490
|
|
Group=cis490
|
|
WorkingDirectory=/opt/cis490
|
|
# /etc/cis490/lab-host.env is written by scripts/install-lab-host.sh;
|
|
# carries FLEET_HOST_ID, BRIDGE, and any operator-supplied overrides.
|
|
EnvironmentFile=/etc/cis490/lab-host.env
|
|
# msfrpc.env only exists after install-tier-3-4.sh; the '-' prefix makes
|
|
# this a no-op on Tier-2-only hosts where it hasn't run yet.
|
|
EnvironmentFile=-/etc/cis490/msfrpc.env
|
|
# Fleet mode: detect host capacity, run that many concurrent episodes
|
|
# per wave with samples drawn from the manifest. Each invocation runs
|
|
# one wave and exits; systemd respawns per Restart= below, giving us
|
|
# a continuous stream of fresh-sample episodes per host. The shipper
|
|
# picks them up as `done.marker` files appear.
|
|
ExecStart=/opt/cis490/.venv/bin/python /opt/cis490/tools/run_fleet.py \
|
|
--data-root /var/lib/cis490/data \
|
|
--manifest /opt/cis490/samples/manifest.toml \
|
|
--waves 1
|
|
Restart=always
|
|
RestartSec=15
|
|
|
|
# Hardening — explicitly grant CAP_NET_RAW for tcpdump (source 4) and
|
|
# CAP_SYS_ADMIN / CAP_PERFMON for perf (source 3) when the operator
|
|
# enables those. Both are inherited by per-episode subprocesses.
|
|
# NoNewPrivileges=false is required because AmbientCapabilities only
|
|
# survives across exec() if NNP is off.
|
|
NoNewPrivileges=false
|
|
PrivateTmp=true
|
|
ProtectSystem=strict
|
|
ProtectHome=true
|
|
# /tmp is needed for per-slot RUN_DIR (cis490-vm-fleet-<slot>) — the
|
|
# fleet runner stages QEMU's sockets + pidfile there.
|
|
ReadWritePaths=/var/lib/cis490 /tmp
|
|
SupplementaryGroups=kvm
|
|
AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN CAP_SYS_ADMIN CAP_PERFMON
|
|
CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN CAP_SYS_ADMIN CAP_PERFMON CAP_DAC_READ_SEARCH
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|